|
| 1 | +# Caching |
| 2 | + |
| 3 | +## How It Works {#how-caching-works} |
| 4 | + |
| 5 | +When a task runs successfully (exit code 0), its terminal output (stdout/stderr) is saved. On the next run, the task runner checks if anything changed: |
| 6 | + |
| 7 | +1. **Arguments** — did the [additional arguments](./cli#additional-arguments) passed to the task change? |
| 8 | +2. **Environment variables** — did any [fingerprinted env vars](./config#envs) change? |
| 9 | +3. **Input files** — did any file that the command reads change? |
| 10 | + |
| 11 | +If everything matches, the cached output is replayed instantly — the command never actually runs. |
| 12 | + |
| 13 | +::: info |
| 14 | +Currently, only terminal output is cached and replayed. Output files (e.g., `dist/`) are not cached — if you delete them, use `--no-cache` to force a re-run. Output file caching is planned for a future release. |
| 15 | +::: |
| 16 | + |
| 17 | +When a cache miss occurs, the task runner tells you exactly why: |
| 18 | + |
| 19 | +``` |
| 20 | +$ vp lint ✗ cache miss: 'src/utils.ts' modified, executing |
| 21 | +$ vp build ✗ cache miss: envs changed, executing |
| 22 | +$ vp test ✗ cache miss: args changed, executing |
| 23 | +``` |
| 24 | + |
| 25 | +## When Is Caching Enabled? {#when-is-caching-enabled} |
| 26 | + |
| 27 | +A command run by `vp run` is either a **task** (has an entry in `vite.config.ts`) or a **script** (only exists in `package.json` with no corresponding task entry). By default, **tasks are cached and scripts are not.** Three layers control whether caching is on: |
| 28 | + |
| 29 | +### 1. Per-task `cache: false` (highest priority, tasks only) |
| 30 | + |
| 31 | +A task can set [`cache: false`](./config#cache) to opt out. This cannot be overridden by `--cache` or `run.cache` — if a task says no caching, it means no caching. |
| 32 | + |
| 33 | +### 2. CLI flags |
| 34 | + |
| 35 | +`--no-cache` disables caching for everything. `--cache` enables caching for both tasks and scripts — equivalent to setting [`run.cache: true`](./config#run-cache) for that invocation. |
| 36 | + |
| 37 | +### 3. Workspace config |
| 38 | + |
| 39 | +The [`run.cache`](./config#run-cache) option in your root `vite.config.ts` controls the default for each category: |
| 40 | + |
| 41 | +| Setting | Default | Effect | |
| 42 | +| --------------- | ------- | ------------------------------------- | |
| 43 | +| `cache.tasks` | `true` | Cache commands that have a task entry | |
| 44 | +| `cache.scripts` | `false` | Cache plain `package.json` scripts | |
| 45 | + |
| 46 | +Use `--cache` to quickly enable script caching, or set `run.cache.scripts: true` in config to enable it permanently. |
| 47 | + |
| 48 | +## Automatic File Tracking {#automatic-file-tracking} |
| 49 | + |
| 50 | +By default, the task runner tracks which files each command reads during execution. When `vp build` runs, it records which files the process opens — your `.ts` source files, `vite.config.ts`, `package.json`, etc. — and records their content hashes. On the next run, it re-checks those hashes to determine if anything changed. |
| 51 | + |
| 52 | +This means caching works out of the box for most commands without any configuration. The tracker also records: |
| 53 | + |
| 54 | +- **File non-existence** — if a command probes for a file that doesn't exist (e.g., `utils.ts` during module resolution), creating that file later correctly invalidates the cache. |
| 55 | +- **Directory listings** — if a command scans a directory (e.g., a test runner looking for `*.test.ts`), adding or removing files in that directory invalidates the cache. |
| 56 | + |
| 57 | +### Over-fingerprinting {#over-fingerprinting} |
| 58 | + |
| 59 | +Automatic tracking can sometimes include more files than necessary, causing unnecessary cache misses: |
| 60 | + |
| 61 | +- **Tool cache files** — some tools maintain their own cache (e.g., TypeScript's `.tsbuildinfo`, Cargo's `target/`). These files may change between runs even when your source code hasn't, causing unnecessary cache invalidation. |
| 62 | +- **Directory listings** — when a command scans a directory (e.g., globbing for `**/*.js`), the task runner sees the directory read but not the glob pattern. Any file added or removed in that directory — even unrelated ones — invalidates the cache. |
| 63 | + |
| 64 | +Use the [`inputs`](./config#inputs) option to exclude noisy files or replace automatic tracking with explicit file patterns: |
| 65 | + |
| 66 | +```ts |
| 67 | +tasks: { |
| 68 | + build: { |
| 69 | + command: 'tsc', |
| 70 | + inputs: [{ auto: true }, '!**/*.tsbuildinfo'], |
| 71 | + }, |
| 72 | +} |
| 73 | +``` |
| 74 | + |
| 75 | +## Environment Variables {#environment-variables} |
| 76 | + |
| 77 | +By default, tasks run in a clean environment — only a small set of common variables (like `PATH`, `HOME`, `CI`) are passed through. Other environment variables are neither visible to the task nor included in the cache fingerprint. |
| 78 | + |
| 79 | +To make a variable affect caching, add it to [`envs`](./config#envs). Changing its value invalidates the cache: |
| 80 | + |
| 81 | +```ts |
| 82 | +tasks: { |
| 83 | + build: { |
| 84 | + command: 'webpack --mode production', |
| 85 | + envs: ['NODE_ENV'], |
| 86 | + }, |
| 87 | +} |
| 88 | +``` |
| 89 | + |
| 90 | +To pass a variable to the task **without** affecting the cache, use [`passThroughEnvs`](./config#pass-through-envs). This is useful for variables like `CI` or `GITHUB_ACTIONS` that should be available but shouldn't trigger a rebuild when they change. |
| 91 | + |
| 92 | +See the [config reference](./config#envs) for details on wildcard patterns and the full list of automatically passed-through variables. |
| 93 | + |
| 94 | +## Cache Sharing {#cache-sharing} |
| 95 | + |
| 96 | +The cache is content-based — if two tasks run the same command with the same inputs, they share the cache entry. This happens naturally when multiple tasks include a common step, either as standalone tasks or as parts of [compound commands](./running-tasks#compound-commands): |
| 97 | + |
| 98 | +```json [package.json] |
| 99 | +{ |
| 100 | + "scripts": { |
| 101 | + "check": "vp lint && vp build", |
| 102 | + "release": "vp lint && deploy-script" |
| 103 | + } |
| 104 | +} |
| 105 | +``` |
| 106 | + |
| 107 | +With caching enabled (e.g. `--cache` or [`run.cache.scripts: true`](./config#run-cache)), running `check` first means the `vp lint` step in `release` is an instant cache hit, since both run the same command against the same files. |
| 108 | + |
| 109 | +## Clearing the Cache {#clearing-the-cache} |
| 110 | + |
| 111 | +```bash |
| 112 | +vp cache clean |
| 113 | +``` |
| 114 | + |
| 115 | +This deletes the entire cache directory. Tasks will run fresh on the next invocation. |
0 commit comments