From 82507283129e811198d6eb4622cb99a99777270c Mon Sep 17 00:00:00 2001 From: branchseer Date: Tue, 10 Mar 2026 13:39:02 +0800 Subject: [PATCH 1/9] docs: add Task Runner user documentation Add guide pages (getting-started, running-tasks, caching, cli) and config reference page for the task runner. Co-Authored-By: Claude Opus 4.6 --- docs/.vitepress/config.mts | 45 ++-- docs/config/task.md | 229 ++++++++++++++++++++ docs/vite/guide/task/caching.md | 59 ++++++ docs/vite/guide/task/cli.md | 71 +++++++ docs/vite/guide/task/getting-started.md | 269 ++++++++++++++++++++++++ docs/vite/guide/task/running-tasks.md | 195 +++++++++++++++++ 6 files changed, 838 insertions(+), 30 deletions(-) create mode 100644 docs/config/task.md create mode 100644 docs/vite/guide/task/caching.md create mode 100644 docs/vite/guide/task/cli.md create mode 100644 docs/vite/guide/task/running-tasks.md diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts index dcbb3abd79..6e4b73ae25 100644 --- a/docs/.vitepress/config.mts +++ b/docs/.vitepress/config.mts @@ -327,40 +327,16 @@ export default extendConfig( link: 'task/getting-started', }, { - text: 'Features', - link: '/guide/task/features', - }, - { - text: 'CLI', - link: '/guide/task/cli', - }, - { - text: 'Migration from Turborepo', - link: '/guide/format/migration-from-turborepo', + text: 'Running Tasks', + link: 'task/running-tasks', }, { - text: 'Migration from Nx', - link: '/guide/format/migration-from-nx', + text: 'Caching', + link: 'task/caching', }, { - text: 'Migration from Lerna', - link: '/guide/format/migration-from-lerna', - }, - { - text: 'Migration from pnpm', - link: '/guide/format/migration-from-pnpm', - }, - { - text: 'Migration from yarn', - link: '/guide/format/migration-from-yarn', - }, - { - text: 'Migration from npm', - link: '/guide/format/migration-from-npm', - }, - { - text: 'Migration from bun', - link: '/guide/format/migration-from-bun', + text: 'CLI', + link: 'task/cli', }, ], }, @@ -604,6 +580,15 @@ export default extendConfig( }, ], }, + { + text: 'Task Runner', + items: [ + { + text: 'Configuring Task Runner', + link: '/config/task', + }, + ], + }, ], '/apis/': [ { diff --git a/docs/config/task.md b/docs/config/task.md new file mode 100644 index 0000000000..eee58fb949 --- /dev/null +++ b/docs/config/task.md @@ -0,0 +1,229 @@ +# Task Runner Config + +The task runner is configured under the `run` field in your `vite.config.ts`: + +```ts [vite.config.ts] +import { defineConfig } from 'vite-plus' + +export default defineConfig({ + run: { + cache: { /* ... */ }, + tasks: { /* ... */ }, + }, +}) +``` + +## `run.cache` {#run-cache} + +- **Type:** `boolean | { scripts?: boolean, tasks?: boolean }` +- **Default:** `{ scripts: false, tasks: true }` + +Global cache settings. Controls whether task results are cached and replayed on subsequent runs. + +```ts [vite.config.ts] +export default defineConfig({ + run: { + cache: { + scripts: true, // Cache package.json scripts (default: false) + tasks: true, // Cache task definitions (default: true) + }, + }, +}) +``` + +Shorthands: `cache: true` enables both, `cache: false` disables both. + +Tasks defined in `vite.config.ts` are cached by default. Plain `package.json` scripts (without a matching task entry) are **not** cached by default. + +## `run.tasks` {#run-tasks} + +- **Type:** `Record` + +Defines named tasks. Each key is a task name that can be run with `vp run `. + +```ts [vite.config.ts] +export default defineConfig({ + run: { + tasks: { + build: { + command: 'vp build', + dependsOn: ['lint'], + }, + lint: { + command: 'vp lint', + }, + }, + }, +}) +``` + +If a task name matches a script in `package.json`, the script is used automatically when `command` is omitted. See [Scripts vs. Tasks](/vite/guide/task/features#scripts-vs-tasks) for details. + +### `command` {#command} + +- **Type:** `string` +- **Default:** matching `package.json` script + +Shell command to run. If omitted, uses the script with the same name from `package.json`. + +```ts +tasks: { + build: { + command: 'vp build', + }, +} +``` + +You cannot define a command in both `vite.config.ts` and `package.json` for the same task name — it's one or the other. + +Commands joined with `&&` are automatically split into independently cached sub-tasks. See [Compound Commands](/vite/guide/task/features#compound-commands). + +### `dependsOn` {#depends-on} + +- **Type:** `string[]` +- **Default:** `[]` + +Tasks that must complete successfully before this one starts. + +```ts +tasks: { + deploy: { + command: 'deploy-script --prod', + dependsOn: ['build', 'test'], + }, +} +``` + +Dependencies can reference tasks in other packages using the `package#task` format: + +```ts +dependsOn: ['@my/core#build', '@my/utils#lint'] +``` + +See [Task Dependencies](/vite/guide/task/features#task-dependencies) for details on how explicit and topological dependencies interact. + +### `cache` {#cache} + +- **Type:** `boolean` +- **Default:** `true` + +Whether to cache this task's output. Set to `false` for tasks that should never be cached, like dev servers: + +```ts +tasks: { + dev: { + command: 'vp dev', + cache: false, + }, +} +``` + +### `envs` {#envs} + +- **Type:** `string[]` +- **Default:** `[]` + +Environment variables included in the cache fingerprint. When any listed variable's value changes, the cache is invalidated. + +```ts +tasks: { + build: { + command: 'vp build', + envs: ['NODE_ENV'], + }, +} +``` + +Wildcard patterns are supported: `VITE_*` matches all variables starting with `VITE_`. + +```ansi +$ NODE_ENV=development vp run build # first run +$ NODE_ENV=production vp run build # cache miss: envs changed +``` + +::: info +Sensitive values (tokens, passwords, API keys) are hashed before being stored in the cache database — plaintext values are never persisted. +::: + +### `passThroughEnvs` {#pass-through-envs} + +- **Type:** `string[]` +- **Default:** see below + +Environment variables passed to the task process but **not** included in the cache fingerprint. Changing these values won't invalidate the cache. + +```ts +tasks: { + build: { + command: 'vp build', + passThroughEnvs: ['CI', 'GITHUB_ACTIONS'], + }, +} +``` + +A set of common environment variables are automatically passed through to all tasks: + +- **System:** `HOME`, `USER`, `PATH`, `SHELL`, `LANG`, `TZ` +- **Node.js:** `NODE_OPTIONS`, `COREPACK_HOME`, `PNPM_HOME` +- **CI/CD:** `CI`, `VERCEL_*`, `NEXT_*` +- **Terminal:** `TERM`, `COLORTERM`, `FORCE_COLOR`, `NO_COLOR` + +### `inputs` {#inputs} + +- **Type:** `Array` +- **Default:** `[{ auto: true }]` (auto-inferred) + +Files to track for cache invalidation. By default, the task runner automatically detects which files a command reads. See [Automatic File Tracking](/vite/guide/task/features#automatic-file-tracking) for how this works. + +**Exclude files** from automatic tracking: + +```ts +tasks: { + build: { + command: 'vp build', + inputs: [{ auto: true }, '!**/*.tsbuildinfo', '!dist/**'], + }, +} +``` + +**Specify explicit files** only (disables automatic tracking): + +```ts +tasks: { + build: { + command: 'vp build', + inputs: ['src/**/*.ts', 'vite.config.ts'], + }, +} +``` + +**Disable file tracking** entirely (cache only on command/env changes): + +```ts +tasks: { + greet: { + command: 'node greet.mjs', + inputs: [], + }, +} +``` + +::: tip +Glob patterns are resolved relative to the package directory, not the task's `cwd`. +::: + +### `cwd` {#cwd} + +- **Type:** `string` +- **Default:** package root + +Working directory for the task, relative to the package root. + +```ts +tasks: { + 'test-e2e': { + command: 'vp test', + cwd: 'tests/e2e', + }, +} +``` diff --git a/docs/vite/guide/task/caching.md b/docs/vite/guide/task/caching.md new file mode 100644 index 0000000000..729935e860 --- /dev/null +++ b/docs/vite/guide/task/caching.md @@ -0,0 +1,59 @@ +# Caching + +## How It Works {#how-caching-works} + +When a task runs successfully (exit code 0), its output is saved. On the next run, the task runner checks if anything changed: + +1. **Command and arguments** — did the command itself change? +2. **Environment variables** — did any [fingerprinted env vars](/config/task#envs) change? +3. **Input files** — did any file that the command reads change? + +If everything matches, the cached output is replayed instantly — the command never actually runs. + +When a cache miss occurs, the task runner tells you exactly why: + +``` +$ vp lint ✗ cache miss: 'src/utils.ts' modified, executing +$ vp build ✗ cache miss: envs changed, executing +$ vp test ✗ cache miss: args changed, executing +``` + +## Automatic File Tracking {#automatic-file-tracking} + +By default, the task runner uses a file system spy to intercept file reads during execution. When `vp build` runs, it detects which files the command 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. + +This means caching works out of the box for most commands without any configuration. The spy also tracks: + +- **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. +- **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. + +When you need more control over which files are tracked, use the [`inputs`](/config/task#inputs) option. + +## Cache Sharing {#cache-sharing} + +The cache is content-based. If two different tasks run the exact same command, they share a single cache entry. For example: + +```ts +tasks: { + check: { + command: 'vp lint && vp build', + }, + release: { + command: 'vp lint && deploy-script', + }, +} +``` + +The `vp lint` sub-command is identical in both tasks, so running `check` first means the `lint` step in `release` is an instant cache hit. + +## Cache Storage {#cache-storage} + +Cache data is stored in a SQLite database at `node_modules/.vite/task-cache/cache.db`. The database supports concurrent access — multiple `vp` processes can read the cache simultaneously. + +## Clearing the Cache {#clearing-the-cache} + +```bash +vp cache clean +``` + +This deletes the entire cache directory. Tasks will run fresh on the next invocation. diff --git a/docs/vite/guide/task/cli.md b/docs/vite/guide/task/cli.md new file mode 100644 index 0000000000..b93a31b7b0 --- /dev/null +++ b/docs/vite/guide/task/cli.md @@ -0,0 +1,71 @@ +# CLI Reference + +## `vp run` {#vp-run} + +Run tasks defined in `vite.config.ts` or `package.json` scripts. + +```bash +vp run [options] [task] [-- additional-args] +``` + +All options must come **before** the task name. If `task` is omitted, an interactive task selector is shown. + +### Task Specifier {#task-specifier} + +- `build` — runs the `build` task in the current package +- `@my/app#build` — runs the `build` task in a specific package + +### Options {#options} + +| Flag | Short | Description | +| --- | --- | --- | +| `--recursive` | `-r` | Run in all workspace packages, in topological order | +| `--transitive` | `-t` | Run in the current package and its transitive dependencies | +| `--workspace-root` | `-w` | Run in the workspace root package | +| `--filter ` | `-F` | Select packages by name, directory, or glob (repeatable) | +| `--ignore-depends-on` | — | Skip explicit `dependsOn` dependencies | +| `--verbose` | `-v` | Show detailed execution summary | +| `--last-details` | — | Display the summary from the last run | + +### Additional Arguments {#additional-arguments} + +Arguments after `--` are passed through to the task command: + +```bash +vp run test -- --reporter verbose +``` + +### Filter Patterns {#filter-patterns} + +| Pattern | Description | +| --- | --- | +| `@my/app` | Exact package name | +| `@my/*` | Glob matching | +| `./packages/app` | By directory | +| `{./packages/app}` | By directory (braced form) | +| `@my/app...` | Package and its dependencies | +| `...@my/core` | Package and its dependents | +| `@my/app^...` | Dependencies only (exclude package itself) | +| `...^@my/core` | Dependents only (exclude package itself) | +| `!@my/utils` | Exclude a package | + +Multiple `--filter` flags are combined as a union. Exclusion filters (`!`) are applied after all inclusions. + +## `vp cache clean` {#vp-cache-clean} + +Delete all cached task results: + +```bash +vp cache clean +``` + +Tasks will run fresh on the next invocation. + +## Exit Codes {#exit-codes} + +| Scenario | Exit code | +| --- | --- | +| All tasks succeed | `0` | +| Single task fails | The task's own exit code | +| Multiple tasks fail | `1` | +| Task not found (non-interactive) | `1` | diff --git a/docs/vite/guide/task/getting-started.md b/docs/vite/guide/task/getting-started.md index e69de29bb2..398c13ad75 100644 --- a/docs/vite/guide/task/getting-started.md +++ b/docs/vite/guide/task/getting-started.md @@ -0,0 +1,269 @@ +# Getting Started + +The Task Runner lets you define, run, and cache tasks in any project — whether it's a single-package project or a large monorepo. + +## Why Use a Task Runner? + +When you work on a project, you frequently run the same commands — build, lint, test. Each time, these commands do the same work if nothing changed. The task runner solves this by: + +- **Caching results** — when nothing changed, tasks complete instantly by replaying previous output +- **Tracking dependencies** — tasks run in the correct order, so `build` always runs before `deploy` +- **Running across packages** — in a monorepo, run tasks across all packages with a single command + +## Defining Tasks + +Tasks are defined in your `vite.config.ts` under the `run` section: + +```ts [vite.config.ts] +import { defineConfig } from 'vite-plus' + +export default defineConfig({ + run: { + tasks: { + build: { + command: 'vp build', + }, + lint: { + command: 'vp lint', + }, + }, + }, +}) +``` + +## Running a Task + +Use `vp run` followed by the task name: + +```bash +vp run build +``` + +``` +$ vp build +vite v8.0.0 building for production... +✓ 4 modules transformed. +dist/index.html 0.12 kB │ gzip: 0.12 kB +dist/assets/index-FvSqcG4U.js 0.69 kB │ gzip: 0.39 kB + +✓ built in 28ms +``` + +## Caching + +Run the same task again — the output is replayed instantly from cache: + +```bash +vp run build +``` + +``` +$ vp build ✓ cache hit, replaying +vite v8.0.0 building for production... +✓ 4 modules transformed. +dist/index.html 0.12 kB │ gzip: 0.12 kB +dist/assets/index-FvSqcG4U.js 0.69 kB │ gzip: 0.39 kB + +✓ built in 28ms + +--- +[vp run] cache hit, 468ms saved. +``` + +The task runner automatically tracks which files your command reads. If you edit a source file and run again, it detects the change and re-runs the task: + +``` +$ vp build ✗ cache miss: 'src/index.ts' modified, executing +``` + +No configuration needed — it just works. + +::: tip +Tasks are cached by default. You can [disable caching](/config/task#cache) for tasks that shouldn't be cached, like dev servers. +::: + +## Scripts vs. Tasks {#scripts-vs-tasks} + +The task runner recognizes two sources of runnable commands: + +1. **Package.json scripts** — any entry in `"scripts"` can be run with `vp run`: + + ```json [package.json] + { + "scripts": { + "build": "vp build", + "test": "vp test" + } + } + ``` + + ```bash + vp run test + ``` + +2. **Task definitions** — entries in `vite.config.ts` that add configuration like dependencies or cache settings: + + ```ts [vite.config.ts] + export default defineConfig({ + run: { + tasks: { + build: { + // No command — uses the "build" script from package.json + dependsOn: ['lint'], + envs: ['NODE_ENV'], + }, + }, + }, + }) + ``` + +A task definition can either reference a `package.json` script (by omitting `command`) or specify its own command. You cannot define a command in both places — it's one or the other. + +::: tip When to Use Which? +Use **`package.json` scripts** for simple commands you want to run standalone (e.g., `"dev": "vp dev"`). Use **task definitions** in `vite.config.ts` when you need caching, dependencies, or other task runner features. You can combine both — define the command in `package.json` and add configuration in `vite.config.ts`. +::: + +::: info +Tasks defined in `vite.config.ts` are cached by default. Plain `package.json` scripts (without a matching task entry) are **not** cached by default. See [Cache Configuration](/config/task#run-cache) for details. +::: + +## Task Dependencies + +Use [`dependsOn`](/config/task#depends-on) to ensure tasks run in the right order: + +```ts [vite.config.ts] +import { defineConfig } from 'vite-plus' + +export default defineConfig({ + run: { + tasks: { + deploy: { + command: 'deploy-script --prod', + cache: false, + dependsOn: ['build', 'test'], + }, + build: { + command: 'vp build', + }, + test: { + command: 'vp test', + }, + }, + }, +}) +``` + +Running `vp run deploy` runs `build` and `test` first: + +``` + ┌─────────┐ ┌────────┐ + │ build │ │ test │ + └────┬────┘ └───┬────┘ + │ │ + └─────┬──────┘ + │ + ┌─────▼─────┐ + │ deploy │ + └───────────┘ +``` + +Dependencies can reference tasks in other packages using the `package#task` format: + +```ts +dependsOn: ['@my/core#build', '@my/utils#lint'] +``` + +## Monorepo Setup + +In a monorepo, each package can define its own tasks in its `vite.config.ts`: + +``` +my-project/ +├── pnpm-workspace.yaml +├── packages/ +│ ├── core/ +│ │ ├── package.json # @my/core +│ │ └── vite.config.ts +│ ├── utils/ +│ │ ├── package.json # @my/utils → depends on @my/core +│ │ └── vite.config.ts +│ └── app/ +│ ├── package.json # @my/app → depends on @my/utils +│ └── vite.config.ts +``` + +Use `-r` (recursive) to run a task across all packages: + +```bash +vp run -r build +``` + +``` +~/packages/core$ vp build +✓ built in 28ms + +~/packages/utils$ vp build +✓ built in 21ms + +~/packages/app$ vp build +✓ built in 26ms + +--- +[vp run] 0/3 cache hit (0%). +``` + +The task runner uses your `package.json` dependency graph to determine the order — `@my/core` builds before `@my/utils`, which builds before `@my/app`. This is called **topological ordering** and is applied automatically. + +When combined with `dependsOn`, both types of ordering work together. For example, with `-r` and `dependsOn: ['lint']` on every package's `build` task: + +``` +core#lint → core#build → utils#lint → utils#build → app#lint → app#build +``` + +Each package's `lint` runs before its `build` (explicit dependency), and packages are ordered by their dependency graph (topological). + +Run it again — each package's task is cached independently: + +``` +~/packages/core$ vp build ✓ cache hit, replaying +~/packages/utils$ vp build ✓ cache hit, replaying +~/packages/app$ vp build ✓ cache hit, replaying + +--- +[vp run] 3/3 cache hit (100%), 468ms saved. +``` + +## Interactive Task Selector + +Run `vp run` without a task name to browse all available tasks: + +```bash +vp run +``` + +``` +Select a task (↑/↓, Enter to run, Esc to clear): + + › build: vp build + lint: vp lint +``` + +Use the arrow keys to navigate, type to search, and press Enter to run. If you mistype a task name, the selector opens with suggestions: + +```bash +vp run buid +``` + +``` +Task "buid" not found. +Select a task (↑/↓, Enter to run, Esc to clear): buid + + › build: vp build +``` + +## What's Next? + +- [Running Tasks](./running-tasks) — package selection, compound commands, and concurrency +- [Caching](./caching) — how caching works, file tracking, and cache sharing +- [CLI Reference](./cli) — all flags and options +- [Config Reference](/config/task) — all task configuration options diff --git a/docs/vite/guide/task/running-tasks.md b/docs/vite/guide/task/running-tasks.md new file mode 100644 index 0000000000..06d978105c --- /dev/null +++ b/docs/vite/guide/task/running-tasks.md @@ -0,0 +1,195 @@ +# Running Tasks + +## Package Selection {#package-selection} + +With no flags, `vp run` runs the task in the package containing your current directory: + +```bash +cd packages/app +vp run build # runs build in @my/app only +``` + +Use `package#task` to target a specific package from anywhere: + +```bash +vp run @my/app#build +``` + +### Recursive (`-r`) {#recursive} + +Run the task across **all** packages in the workspace: + +```bash +vp run -r build # builds every package, dependencies first +``` + +### Transitive (`-t`) {#transitive} + +Run the task in a package **and all its dependencies**: + +```bash +vp run -t @my/app#build +``` + +If `@my/app` depends on `@my/utils` which depends on `@my/core`, this builds all three in dependency order. You can also use `--filter "@my/app..."` for the same result. + +### Filter (`--filter`) {#filter} + +Select packages by name, directory, or glob pattern. The task name always comes **after** the flags: + +```bash +# By name +vp run --filter @my/app build + +# By glob +vp run --filter "@my/*" build + +# By directory +vp run --filter ./packages/app build + +# With dependencies +vp run --filter "@my/app..." build # app + all its dependencies + +# With dependents +vp run --filter "...@my/core" build # core + everything that depends on it + +# Exclude packages +vp run --filter "@my/*" --filter "!@my/utils" build +``` + +Multiple `--filter` flags produce a union of the selected packages. + +::: tip +The `--filter` syntax is compatible with pnpm. Most pnpm filter expressions work identically. +::: + +### Workspace Root (`-w`) {#workspace-root} + +Explicitly select the workspace root package: + +```bash +vp run -w build +``` + +## Compound Commands {#compound-commands} + +Commands joined with `&&` are split into independently cached sub-tasks: + +```ts [vite.config.ts] +export default defineConfig({ + run: { + tasks: { + check: { + command: 'vp lint && vp build', + }, + }, + }, +}) +``` + +``` +$ vp lint +Found 0 warnings and 0 errors. + +$ vp build +✓ built in 28ms + +--- +[vp run] 0/2 cache hit (0%). +``` + +Each sub-task has its own cache entry. On the next run, if only `.ts` files changed but lint passes, only `vp build` re-runs: + +``` +$ vp lint ✓ cache hit, replaying +$ vp build ✗ cache miss: 'src/index.ts' modified, executing +✓ built in 30ms + +--- +[vp run] 1/2 cache hit (50%), 120ms saved. +``` + +### Nested `vp run` {#nested-vp-run} + +When a command contains `vp run`, it is **expanded at plan time** into the execution graph — no extra process is spawned. This means each sub-task is cached independently and output is shown flat: + +```json [package.json] +{ + "scripts": { + "ci": "vp run lint && vp run test && vp run build" + } +} +``` + +Running `vp run ci` expands into three separate tasks, each with its own cache entry: + +``` +┌────────┐ +│ lint │ +└───┬────┘ + │ +┌───▼────┐ +│ test │ +└───┬────┘ + │ +┌───▼────┐ +│ build │ +└────────┘ +``` + +Flags work inside nested scripts too. For example, `vp run -r build` inside a script expands into individual build tasks for every package. + +::: details Self-Referencing Scripts +A common monorepo pattern is a root script that runs a task recursively: + +```json [package.json (root)] +{ + "scripts": { + "build": "vp run -r build" + } +} +``` + +This creates a potential recursion: root's `build` → `vp run -r build` → includes root's `build` → ... The task runner detects this and prunes the self-reference automatically, so other packages' builds run normally without infinite loops. +::: + +## Concurrency {#concurrency} + +When running multiple tasks (e.g., with `-r`), the task runner executes independent tasks in parallel. Tasks that have no dependency relationship run concurrently, while dependent tasks wait for their dependencies to complete. + +For a single task, the process inherits the terminal directly — interactive programs, progress bars, and stdin all work normally. For multiple concurrent tasks, output is captured and displayed in order to avoid interleaving. + +## Execution Summary {#execution-summary} + +Use `-v` to see a detailed execution summary: + +```bash +vp run -r -v build +``` + +``` +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + Vite+ Task Runner • Execution Summary +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +Statistics: 3 tasks • 3 cache hits • 0 cache misses +Performance: 100% cache hit rate, 468ms saved in total + +Task Details: +──────────────────────────────────────────────── + [1] @my/core#build: ~/packages/core$ vp build ✓ + → Cache hit - output replayed - 200ms saved + ······················································· + [2] @my/utils#build: ~/packages/utils$ vp build ✓ + → Cache hit - output replayed - 150ms saved + ······················································· + [3] @my/app#build: ~/packages/app$ vp build ✓ + → Cache hit - output replayed - 118ms saved +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +``` + +Use `--last-details` to recall the summary from the last run without re-executing: + +```bash +vp run --last-details +``` From a5cd1393d676ec4ab819d778ab9e743cdcf714b8 Mon Sep 17 00:00:00 2001 From: branchseer Date: Tue, 10 Mar 2026 15:26:44 +0800 Subject: [PATCH 2/9] docs: move task runner config into guide directory and fix links Move docs/config/task.md to docs/vite/guide/task/config.md so the Config sidebar link works within the /vite/guide/ base. Update all cross-references to use relative paths and fix stale features.md links. Co-Authored-By: Claude Opus 4.6 --- docs/.vitepress/config.mts | 8 +- docs/vite/guide/task/caching.md | 4 +- .../task.md => vite/guide/task/config.md} | 10 +- docs/vite/guide/task/getting-started.md | 153 +++++------------- 4 files changed, 57 insertions(+), 118 deletions(-) rename docs/{config/task.md => vite/guide/task/config.md} (91%) diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts index 6e4b73ae25..f531d60c2c 100644 --- a/docs/.vitepress/config.mts +++ b/docs/.vitepress/config.mts @@ -71,7 +71,7 @@ export default extendConfig( { text: 'Test', link: '/config/test' }, { text: 'Lint', link: '/config/lint' }, { text: 'Format', link: '/config/format' }, - { text: 'Task Runner', link: '/config/task' }, + { text: 'Task Runner', link: '/vite/guide/task/config' }, { text: 'Package Manager', link: '/config/package-manager' }, ], }, @@ -338,6 +338,10 @@ export default extendConfig( text: 'CLI', link: 'task/cli', }, + { + text: 'Config', + link: 'task/config', + }, ], }, { @@ -585,7 +589,7 @@ export default extendConfig( items: [ { text: 'Configuring Task Runner', - link: '/config/task', + link: '/vite/guide/task/config', }, ], }, diff --git a/docs/vite/guide/task/caching.md b/docs/vite/guide/task/caching.md index 729935e860..6ed94ddc3c 100644 --- a/docs/vite/guide/task/caching.md +++ b/docs/vite/guide/task/caching.md @@ -5,7 +5,7 @@ When a task runs successfully (exit code 0), its output is saved. On the next run, the task runner checks if anything changed: 1. **Command and arguments** — did the command itself change? -2. **Environment variables** — did any [fingerprinted env vars](/config/task#envs) change? +2. **Environment variables** — did any [fingerprinted env vars](./config#envs) change? 3. **Input files** — did any file that the command reads change? If everything matches, the cached output is replayed instantly — the command never actually runs. @@ -27,7 +27,7 @@ This means caching works out of the box for most commands without any configurat - **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. - **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. -When you need more control over which files are tracked, use the [`inputs`](/config/task#inputs) option. +When you need more control over which files are tracked, use the [`inputs`](./config#inputs) option. ## Cache Sharing {#cache-sharing} diff --git a/docs/config/task.md b/docs/vite/guide/task/config.md similarity index 91% rename from docs/config/task.md rename to docs/vite/guide/task/config.md index eee58fb949..a8d832a2e4 100644 --- a/docs/config/task.md +++ b/docs/vite/guide/task/config.md @@ -57,7 +57,7 @@ export default defineConfig({ }) ``` -If a task name matches a script in `package.json`, the script is used automatically when `command` is omitted. See [Scripts vs. Tasks](/vite/guide/task/features#scripts-vs-tasks) for details. +If a task name matches a script in `package.json`, the script is used automatically when `command` is omitted. See [Getting Started](./getting-started#task-definitions) for details. ### `command` {#command} @@ -76,7 +76,7 @@ tasks: { You cannot define a command in both `vite.config.ts` and `package.json` for the same task name — it's one or the other. -Commands joined with `&&` are automatically split into independently cached sub-tasks. See [Compound Commands](/vite/guide/task/features#compound-commands). +Commands joined with `&&` are automatically split into independently cached sub-tasks. See [Compound Commands](./running-tasks#compound-commands). ### `dependsOn` {#depends-on} @@ -100,7 +100,7 @@ Dependencies can reference tasks in other packages using the `package#task` form dependsOn: ['@my/core#build', '@my/utils#lint'] ``` -See [Task Dependencies](/vite/guide/task/features#task-dependencies) for details on how explicit and topological dependencies interact. +See [Task Dependencies](./getting-started#task-dependencies) for details on how explicit and topological dependencies interact. ### `cache` {#cache} @@ -136,7 +136,7 @@ tasks: { Wildcard patterns are supported: `VITE_*` matches all variables starting with `VITE_`. -```ansi +``` $ NODE_ENV=development vp run build # first run $ NODE_ENV=production vp run build # cache miss: envs changed ``` @@ -173,7 +173,7 @@ A set of common environment variables are automatically passed through to all ta - **Type:** `Array` - **Default:** `[{ auto: true }]` (auto-inferred) -Files to track for cache invalidation. By default, the task runner automatically detects which files a command reads. See [Automatic File Tracking](/vite/guide/task/features#automatic-file-tracking) for how this works. +Files to track for cache invalidation. By default, the task runner automatically detects which files a command reads. See [Automatic File Tracking](./caching#automatic-file-tracking) for how this works. **Exclude files** from automatic tracking: diff --git a/docs/vite/guide/task/getting-started.md b/docs/vite/guide/task/getting-started.md index 398c13ad75..bdc618830b 100644 --- a/docs/vite/guide/task/getting-started.md +++ b/docs/vite/guide/task/getting-started.md @@ -1,40 +1,24 @@ # Getting Started -The Task Runner lets you define, run, and cache tasks in any project — whether it's a single-package project or a large monorepo. +## Overview -## Why Use a Task Runner? +The Vite+ Task Runner is a high-performance task execution system built into Vite+. It caches task results so repeated runs complete instantly, orders tasks by their dependencies, and scales across monorepo packages — all with minimal configuration. -When you work on a project, you frequently run the same commands — build, lint, test. Each time, these commands do the same work if nothing changed. The task runner solves this by: +It works with the scripts you already have in `package.json`. You can add task definitions in `vite.config.ts` when you need more control over dependencies and caching. -- **Caching results** — when nothing changed, tasks complete instantly by replaying previous output -- **Tracking dependencies** — tasks run in the correct order, so `build` always runs before `deploy` -- **Running across packages** — in a monorepo, run tasks across all packages with a single command +## Running Scripts -## Defining Tasks +If your project already has scripts in `package.json`, you can run them with `vp run` right away — no configuration needed: -Tasks are defined in your `vite.config.ts` under the `run` section: - -```ts [vite.config.ts] -import { defineConfig } from 'vite-plus' - -export default defineConfig({ - run: { - tasks: { - build: { - command: 'vp build', - }, - lint: { - command: 'vp lint', - }, - }, - }, -}) +```json [package.json] +{ + "scripts": { + "build": "vp build", + "test": "vp test" + } +} ``` -## Running a Task - -Use `vp run` followed by the task name: - ```bash vp run build ``` @@ -51,85 +35,40 @@ dist/assets/index-FvSqcG4U.js 0.69 kB │ gzip: 0.39 kB ## Caching -Run the same task again — the output is replayed instantly from cache: +Plain `package.json` scripts are not cached by default. Pass `--cache` to try it out: ```bash -vp run build +vp run --cache build ``` ``` -$ vp build ✓ cache hit, replaying -vite v8.0.0 building for production... -✓ 4 modules transformed. -dist/index.html 0.12 kB │ gzip: 0.12 kB -dist/assets/index-FvSqcG4U.js 0.69 kB │ gzip: 0.39 kB +$ vp build +✓ built in 28ms +``` + +Run it again — the output is replayed instantly from cache: +``` +$ vp build ✓ cache hit, replaying ✓ built in 28ms --- [vp run] cache hit, 468ms saved. ``` -The task runner automatically tracks which files your command reads. If you edit a source file and run again, it detects the change and re-runs the task: +Edit a source file and run again — the task runner detects the change and re-runs: ``` $ vp build ✗ cache miss: 'src/index.ts' modified, executing ``` -No configuration needed — it just works. +The task runner automatically tracks which files your command reads. No configuration needed. -::: tip -Tasks are cached by default. You can [disable caching](/config/task#cache) for tasks that shouldn't be cached, like dev servers. -::: +The `--cache` flag is a quick way to try caching, but the default behavior may not suit every task — you may need to control which files or environment variables affect the cache. To configure caching properly and enable it permanently, define the task in `vite.config.ts`. -## Scripts vs. Tasks {#scripts-vs-tasks} - -The task runner recognizes two sources of runnable commands: - -1. **Package.json scripts** — any entry in `"scripts"` can be run with `vp run`: - - ```json [package.json] - { - "scripts": { - "build": "vp build", - "test": "vp test" - } - } - ``` - - ```bash - vp run test - ``` - -2. **Task definitions** — entries in `vite.config.ts` that add configuration like dependencies or cache settings: - - ```ts [vite.config.ts] - export default defineConfig({ - run: { - tasks: { - build: { - // No command — uses the "build" script from package.json - dependsOn: ['lint'], - envs: ['NODE_ENV'], - }, - }, - }, - }) - ``` - -A task definition can either reference a `package.json` script (by omitting `command`) or specify its own command. You cannot define a command in both places — it's one or the other. - -::: tip When to Use Which? -Use **`package.json` scripts** for simple commands you want to run standalone (e.g., `"dev": "vp dev"`). Use **task definitions** in `vite.config.ts` when you need caching, dependencies, or other task runner features. You can combine both — define the command in `package.json` and add configuration in `vite.config.ts`. -::: +## Task Definitions {#task-definitions} -::: info -Tasks defined in `vite.config.ts` are cached by default. Plain `package.json` scripts (without a matching task entry) are **not** cached by default. See [Cache Configuration](/config/task#run-cache) for details. -::: - -## Task Dependencies - -Use [`dependsOn`](/config/task#depends-on) to ensure tasks run in the right order: +Task definitions in `vite.config.ts` enable caching by default and give you more control — dependencies, environment variables, and custom inputs: ```ts [vite.config.ts] import { defineConfig } from 'vite-plus' @@ -137,23 +76,32 @@ import { defineConfig } from 'vite-plus' export default defineConfig({ run: { tasks: { + build: { + // Uses the "build" script from package.json + dependsOn: ['lint'], + envs: ['NODE_ENV'], + }, deploy: { command: 'deploy-script --prod', cache: false, dependsOn: ['build', 'test'], }, - build: { - command: 'vp build', - }, - test: { - command: 'vp test', - }, }, }, }) ``` -Running `vp run deploy` runs `build` and `test` first: +A task definition can either reference a `package.json` script (by omitting `command`) or specify its own command. You cannot define a command in both places. + +::: info +Tasks defined in `vite.config.ts` are cached by default. Plain `package.json` scripts (without a matching task entry) are **not** cached by default. See [Cache Configuration](./config#run-cache) for details. +::: + +See [Config Reference](./config) for all available task options. + +## Task Dependencies + +Use [`dependsOn`](./config#depends-on) to ensure tasks run in the right order. Running `vp run deploy` with the config above runs `build` and `test` first: ``` ┌─────────┐ ┌────────┐ @@ -235,7 +183,7 @@ Run it again — each package's task is cached independently: ## Interactive Task Selector -Run `vp run` without a task name to browse all available tasks: +Run `vp run` without a task name to browse available tasks: ```bash vp run @@ -248,22 +196,9 @@ Select a task (↑/↓, Enter to run, Esc to clear): lint: vp lint ``` -Use the arrow keys to navigate, type to search, and press Enter to run. If you mistype a task name, the selector opens with suggestions: - -```bash -vp run buid -``` - -``` -Task "buid" not found. -Select a task (↑/↓, Enter to run, Esc to clear): buid - - › build: vp build -``` - ## What's Next? - [Running Tasks](./running-tasks) — package selection, compound commands, and concurrency - [Caching](./caching) — how caching works, file tracking, and cache sharing - [CLI Reference](./cli) — all flags and options -- [Config Reference](/config/task) — all task configuration options +- [Config Reference](./config) — all task configuration options From 3b0869dfc875a3b610b02095298bb76990eb3c1b Mon Sep 17 00:00:00 2001 From: branchseer Date: Tue, 10 Mar 2026 15:33:42 +0800 Subject: [PATCH 3/9] update overview --- docs/vite/guide/task/getting-started.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/vite/guide/task/getting-started.md b/docs/vite/guide/task/getting-started.md index bdc618830b..0fb8611dd0 100644 --- a/docs/vite/guide/task/getting-started.md +++ b/docs/vite/guide/task/getting-started.md @@ -2,9 +2,9 @@ ## Overview -The Vite+ Task Runner is a high-performance task execution system built into Vite+. It caches task results so repeated runs complete instantly, orders tasks by their dependencies, and scales across monorepo packages — all with minimal configuration. +`vp run` works like `pnpm run` — it runs the scripts in your `package.json` — but adds caching, dependency ordering, and monorepo-aware execution on top. It works in both single-package projects and monorepos. -It works with the scripts you already have in `package.json`. You can add task definitions in `vite.config.ts` when you need more control over dependencies and caching. +You can add task definitions in `vite.config.ts` when you need more control over dependencies and caching. ## Running Scripts From de00a83ab5e534d4580c49b19193140b5aaa1287 Mon Sep 17 00:00:00 2001 From: branchseer Date: Tue, 10 Mar 2026 15:40:07 +0800 Subject: [PATCH 4/9] docs: add caching defaults section and update overview MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add "When Is Caching Enabled?" section to caching page with full resolution flowchart (CLI flags → workspace config → per-task config). Add --cache/--no-cache flags to CLI options table. Update overview to mention pnpm run similarity and single-package/monorepo support. Co-Authored-By: Claude Opus 4.6 --- docs/vite/guide/task/caching.md | 38 +++++++++++++++++++++++++++++++++ docs/vite/guide/task/cli.md | 2 ++ docs/vite/guide/task/config.md | 2 +- 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/docs/vite/guide/task/caching.md b/docs/vite/guide/task/caching.md index 6ed94ddc3c..13083c872a 100644 --- a/docs/vite/guide/task/caching.md +++ b/docs/vite/guide/task/caching.md @@ -18,6 +18,44 @@ $ vp build ✗ cache miss: envs changed, executing $ vp test ✗ cache miss: args changed, executing ``` +## When Is Caching Enabled? {#when-is-caching-enabled} + +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.** + +The full resolution order: + +``` +--no-cache on the command line? +├─ YES → NOT CACHED (overrides everything) +└─ NO + │ + --cache on the command line? + ├─ YES → acts as cache: true (enables both scripts and tasks) + └─ NO → uses workspace config (run.cache) + │ + Does the command have a task entry in vite.config.ts? + │ + ├─ YES (task) ────────────────────────────────── + │ │ + │ Global cache.tasks enabled? (default: true) + │ ├─ NO → NOT CACHED + │ └─ YES + │ │ + │ Per-task cache set to false? + │ ├─ YES → NOT CACHED (--cache does NOT override this) + │ └─ NO → CACHED ← default for tasks + │ + └─ NO (script) ───────────────────────────────── + │ + Global cache.scripts enabled? (default: false) + ├─ YES → CACHED + └─ NO → NOT CACHED ← default for scripts +``` + +`--no-cache` turns off caching for everything. `--cache` is equivalent to `cache: true` — it enables both `cache.tasks` and `cache.scripts`, but cannot override a task's per-task `cache: false`. + +See [`run.cache`](./config#run-cache) for workspace-level configuration. + ## Automatic File Tracking {#automatic-file-tracking} By default, the task runner uses a file system spy to intercept file reads during execution. When `vp build` runs, it detects which files the command 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. diff --git a/docs/vite/guide/task/cli.md b/docs/vite/guide/task/cli.md index b93a31b7b0..b58acdc57d 100644 --- a/docs/vite/guide/task/cli.md +++ b/docs/vite/guide/task/cli.md @@ -23,6 +23,8 @@ All options must come **before** the task name. If `task` is omitted, an interac | `--transitive` | `-t` | Run in the current package and its transitive dependencies | | `--workspace-root` | `-w` | Run in the workspace root package | | `--filter ` | `-F` | Select packages by name, directory, or glob (repeatable) | +| `--cache` | — | Enable caching for all tasks and scripts | +| `--no-cache` | — | Disable caching entirely | | `--ignore-depends-on` | — | Skip explicit `dependsOn` dependencies | | `--verbose` | `-v` | Show detailed execution summary | | `--last-details` | — | Display the summary from the last run | diff --git a/docs/vite/guide/task/config.md b/docs/vite/guide/task/config.md index a8d832a2e4..c6a780309d 100644 --- a/docs/vite/guide/task/config.md +++ b/docs/vite/guide/task/config.md @@ -33,7 +33,7 @@ export default defineConfig({ Shorthands: `cache: true` enables both, `cache: false` disables both. -Tasks defined in `vite.config.ts` are cached by default. Plain `package.json` scripts (without a matching task entry) are **not** cached by default. +Tasks defined in `vite.config.ts` are cached by default. Plain `package.json` scripts (without a matching task entry) are **not** cached by default. See [When Is Caching Enabled?](./caching#when-is-caching-enabled) for the full resolution order including CLI overrides. ## `run.tasks` {#run-tasks} From 66471f248302d7e095bb1f7ffdbd4be37e1c982d Mon Sep 17 00:00:00 2001 From: branchseer Date: Tue, 10 Mar 2026 15:40:49 +0800 Subject: [PATCH 5/9] docs: remove exit codes section from task runner CLI reference Co-Authored-By: Claude Opus 4.6 --- docs/vite/guide/task/cli.md | 9 --------- 1 file changed, 9 deletions(-) diff --git a/docs/vite/guide/task/cli.md b/docs/vite/guide/task/cli.md index b58acdc57d..4a352215d1 100644 --- a/docs/vite/guide/task/cli.md +++ b/docs/vite/guide/task/cli.md @@ -62,12 +62,3 @@ vp cache clean ``` Tasks will run fresh on the next invocation. - -## Exit Codes {#exit-codes} - -| Scenario | Exit code | -| --- | --- | -| All tasks succeed | `0` | -| Single task fails | The task's own exit code | -| Multiple tasks fail | `1` | -| Task not found (non-interactive) | `1` | From d1cd76e3ba725b3e9c8cbaee5155e3ec769fcae1 Mon Sep 17 00:00:00 2001 From: branchseer Date: Tue, 10 Mar 2026 16:52:46 +0800 Subject: [PATCH 6/9] docs: refine task runner documentation - Rewrite caching defaults section with correct priority ordering - Add over-fingerprinting and environment variables sections - Add output file caching limitation note - Move interactive task selector to CLI page - Simplify filter docs with pnpm compatibility mention - Remove concurrency section and sensitive values info - Rephrase nested vp run and fix CLI usage syntax Co-Authored-By: Claude Opus 4.6 --- docs/vite/guide/task/caching.md | 102 ++++++++++++++---------- docs/vite/guide/task/cli.md | 15 +++- docs/vite/guide/task/config.md | 4 - docs/vite/guide/task/getting-started.md | 15 ---- docs/vite/guide/task/running-tasks.md | 14 +--- 5 files changed, 74 insertions(+), 76 deletions(-) diff --git a/docs/vite/guide/task/caching.md b/docs/vite/guide/task/caching.md index 13083c872a..b7dfc0bc84 100644 --- a/docs/vite/guide/task/caching.md +++ b/docs/vite/guide/task/caching.md @@ -2,14 +2,18 @@ ## How It Works {#how-caching-works} -When a task runs successfully (exit code 0), its output is saved. On the next run, the task runner checks if anything changed: +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: -1. **Command and arguments** — did the command itself change? +1. **Arguments** — did the [additional arguments](./cli#additional-arguments) passed to the task change? 2. **Environment variables** — did any [fingerprinted env vars](./config#envs) change? 3. **Input files** — did any file that the command reads change? If everything matches, the cached output is replayed instantly — the command never actually runs. +::: info +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. +::: + When a cache miss occurs, the task runner tells you exactly why: ``` @@ -20,56 +24,76 @@ $ vp test ✗ cache miss: args changed, executing ## When Is Caching Enabled? {#when-is-caching-enabled} -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.** +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: -The full resolution order: +### 1. Per-task `cache: false` (highest priority, tasks only) -``` ---no-cache on the command line? -├─ YES → NOT CACHED (overrides everything) -└─ NO - │ - --cache on the command line? - ├─ YES → acts as cache: true (enables both scripts and tasks) - └─ NO → uses workspace config (run.cache) - │ - Does the command have a task entry in vite.config.ts? - │ - ├─ YES (task) ────────────────────────────────── - │ │ - │ Global cache.tasks enabled? (default: true) - │ ├─ NO → NOT CACHED - │ └─ YES - │ │ - │ Per-task cache set to false? - │ ├─ YES → NOT CACHED (--cache does NOT override this) - │ └─ NO → CACHED ← default for tasks - │ - └─ NO (script) ───────────────────────────────── - │ - Global cache.scripts enabled? (default: false) - ├─ YES → CACHED - └─ NO → NOT CACHED ← default for scripts -``` +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. + +### 2. CLI flags -`--no-cache` turns off caching for everything. `--cache` is equivalent to `cache: true` — it enables both `cache.tasks` and `cache.scripts`, but cannot override a task's per-task `cache: false`. +`--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. -See [`run.cache`](./config#run-cache) for workspace-level configuration. +### 3. Workspace config + +The [`run.cache`](./config#run-cache) option in your root `vite.config.ts` controls the default for each category: + +| Setting | Default | Effect | +| --- | --- | --- | +| `cache.tasks` | `true` | Cache commands that have a task entry | +| `cache.scripts` | `false` | Cache plain `package.json` scripts | + +Use `--cache` to quickly enable script caching, or set `run.cache.scripts: true` in config to enable it permanently. ## Automatic File Tracking {#automatic-file-tracking} -By default, the task runner uses a file system spy to intercept file reads during execution. When `vp build` runs, it detects which files the command 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. +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. -This means caching works out of the box for most commands without any configuration. The spy also tracks: +This means caching works out of the box for most commands without any configuration. The tracker also records: - **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. - **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. -When you need more control over which files are tracked, use the [`inputs`](./config#inputs) option. +### Over-fingerprinting {#over-fingerprinting} + +Automatic tracking can sometimes include more files than necessary, causing unnecessary cache misses: + +- **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. +- **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. + +Use the [`inputs`](./config#inputs) option to exclude noisy files or replace automatic tracking with explicit file patterns: + +```ts +tasks: { + build: { + command: 'tsc', + inputs: [{ auto: true }, '!**/*.tsbuildinfo'], + }, +} +``` + +## Environment Variables {#environment-variables} + +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. + +To make a variable affect caching, add it to [`envs`](./config#envs). Changing its value invalidates the cache: + +```ts +tasks: { + build: { + command: 'vp build', + envs: ['NODE_ENV', 'VITE_*'], + }, +} +``` + +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. + +See the [config reference](./config#envs) for details on wildcard patterns and the full list of automatically passed-through variables. ## Cache Sharing {#cache-sharing} -The cache is content-based. If two different tasks run the exact same command, they share a single cache entry. For example: +Commands joined with `&&` are [split into independent sub-tasks](./running-tasks#compound-commands), each cached separately. The cache is content-based, so if two different tasks share a sub-command, they share its cache entry. For example: ```ts tasks: { @@ -84,10 +108,6 @@ tasks: { The `vp lint` sub-command is identical in both tasks, so running `check` first means the `lint` step in `release` is an instant cache hit. -## Cache Storage {#cache-storage} - -Cache data is stored in a SQLite database at `node_modules/.vite/task-cache/cache.db`. The database supports concurrent access — multiple `vp` processes can read the cache simultaneously. - ## Clearing the Cache {#clearing-the-cache} ```bash diff --git a/docs/vite/guide/task/cli.md b/docs/vite/guide/task/cli.md index 4a352215d1..9d304c4970 100644 --- a/docs/vite/guide/task/cli.md +++ b/docs/vite/guide/task/cli.md @@ -5,10 +5,17 @@ Run tasks defined in `vite.config.ts` or `package.json` scripts. ```bash -vp run [options] [task] [-- additional-args] +vp run [options] [task] [additional-args] ``` -All options must come **before** the task name. If `task` is omitted, an interactive task selector is shown. +If `task` is omitted, an interactive selector is shown: + +``` +Select a task (↑/↓, Enter to run, Esc to clear): + + › build: vp build + lint: vp lint +``` ### Task Specifier {#task-specifier} @@ -31,10 +38,10 @@ All options must come **before** the task name. If `task` is omitted, an interac ### Additional Arguments {#additional-arguments} -Arguments after `--` are passed through to the task command: +Arguments after the task name are passed through to the task command: ```bash -vp run test -- --reporter verbose +vp run test --reporter verbose ``` ### Filter Patterns {#filter-patterns} diff --git a/docs/vite/guide/task/config.md b/docs/vite/guide/task/config.md index c6a780309d..c61aeed3f8 100644 --- a/docs/vite/guide/task/config.md +++ b/docs/vite/guide/task/config.md @@ -141,10 +141,6 @@ $ NODE_ENV=development vp run build # first run $ NODE_ENV=production vp run build # cache miss: envs changed ``` -::: info -Sensitive values (tokens, passwords, API keys) are hashed before being stored in the cache database — plaintext values are never persisted. -::: - ### `passThroughEnvs` {#pass-through-envs} - **Type:** `string[]` diff --git a/docs/vite/guide/task/getting-started.md b/docs/vite/guide/task/getting-started.md index 0fb8611dd0..615838f52d 100644 --- a/docs/vite/guide/task/getting-started.md +++ b/docs/vite/guide/task/getting-started.md @@ -181,21 +181,6 @@ Run it again — each package's task is cached independently: [vp run] 3/3 cache hit (100%), 468ms saved. ``` -## Interactive Task Selector - -Run `vp run` without a task name to browse available tasks: - -```bash -vp run -``` - -``` -Select a task (↑/↓, Enter to run, Esc to clear): - - › build: vp build - lint: vp lint -``` - ## What's Next? - [Running Tasks](./running-tasks) — package selection, compound commands, and concurrency diff --git a/docs/vite/guide/task/running-tasks.md b/docs/vite/guide/task/running-tasks.md index 06d978105c..452a423f7a 100644 --- a/docs/vite/guide/task/running-tasks.md +++ b/docs/vite/guide/task/running-tasks.md @@ -35,7 +35,7 @@ If `@my/app` depends on `@my/utils` which depends on `@my/core`, this builds all ### Filter (`--filter`) {#filter} -Select packages by name, directory, or glob pattern. The task name always comes **after** the flags: +Select packages by name, directory, or glob pattern. The syntax is compatible with pnpm's `--filter`: ```bash # By name @@ -59,10 +59,6 @@ vp run --filter "@my/*" --filter "!@my/utils" build Multiple `--filter` flags produce a union of the selected packages. -::: tip -The `--filter` syntax is compatible with pnpm. Most pnpm filter expressions work identically. -::: - ### Workspace Root (`-w`) {#workspace-root} Explicitly select the workspace root package: @@ -111,7 +107,7 @@ $ vp build ✗ cache miss: 'src/index.ts' modified, executing ### Nested `vp run` {#nested-vp-run} -When a command contains `vp run`, it is **expanded at plan time** into the execution graph — no extra process is spawned. This means each sub-task is cached independently and output is shown flat: +When a command contains `vp run`, the task runner **inlines it as separate tasks** rather than spawning a nested process. Each sub-task is cached independently and output is shown flat: ```json [package.json] { @@ -153,12 +149,6 @@ A common monorepo pattern is a root script that runs a task recursively: This creates a potential recursion: root's `build` → `vp run -r build` → includes root's `build` → ... The task runner detects this and prunes the self-reference automatically, so other packages' builds run normally without infinite loops. ::: -## Concurrency {#concurrency} - -When running multiple tasks (e.g., with `-r`), the task runner executes independent tasks in parallel. Tasks that have no dependency relationship run concurrently, while dependent tasks wait for their dependencies to complete. - -For a single task, the process inherits the terminal directly — interactive programs, progress bars, and stdin all work normally. For multiple concurrent tasks, output is captured and displayed in order to avoid interleaving. - ## Execution Summary {#execution-summary} Use `-v` to see a detailed execution summary: From 9b426d3104dc7a9f5e8e6728ab16cfd06010f97c Mon Sep 17 00:00:00 2001 From: branchseer Date: Tue, 10 Mar 2026 17:26:31 +0800 Subject: [PATCH 7/9] docs: improve task runner docs clarity and consistency - Rename "Monorepo Setup" to "Running Across Packages" - Rename "Task Specifier" to "Task Argument" with lead-in sentence - Update info box to link to "When Is Caching Enabled?" instead of config - Use package.json scripts in compound commands and cache sharing examples - Note that script caching must be explicitly enabled - Use third-party tool (webpack) in environment variables example Co-Authored-By: Claude Opus 4.6 --- docs/vite/guide/task/caching.md | 22 +++++----- docs/vite/guide/task/cli.md | 4 +- docs/vite/guide/task/getting-started.md | 58 +++---------------------- docs/vite/guide/task/running-tasks.md | 20 ++++----- 4 files changed, 26 insertions(+), 78 deletions(-) diff --git a/docs/vite/guide/task/caching.md b/docs/vite/guide/task/caching.md index b7dfc0bc84..b9b85caea8 100644 --- a/docs/vite/guide/task/caching.md +++ b/docs/vite/guide/task/caching.md @@ -81,8 +81,8 @@ To make a variable affect caching, add it to [`envs`](./config#envs). Changing i ```ts tasks: { build: { - command: 'vp build', - envs: ['NODE_ENV', 'VITE_*'], + command: 'webpack --mode production', + envs: ['NODE_ENV'], }, } ``` @@ -93,20 +93,18 @@ See the [config reference](./config#envs) for details on wildcard patterns and t ## Cache Sharing {#cache-sharing} -Commands joined with `&&` are [split into independent sub-tasks](./running-tasks#compound-commands), each cached separately. The cache is content-based, so if two different tasks share a sub-command, they share its cache entry. For example: +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): -```ts -tasks: { - check: { - command: 'vp lint && vp build', - }, - release: { - command: 'vp lint && deploy-script', - }, +```json [package.json] +{ + "scripts": { + "check": "vp lint && vp build", + "release": "vp lint && deploy-script" + } } ``` -The `vp lint` sub-command is identical in both tasks, so running `check` first means the `lint` step in `release` is an instant cache hit. +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. ## Clearing the Cache {#clearing-the-cache} diff --git a/docs/vite/guide/task/cli.md b/docs/vite/guide/task/cli.md index 9d304c4970..52833efe79 100644 --- a/docs/vite/guide/task/cli.md +++ b/docs/vite/guide/task/cli.md @@ -17,7 +17,9 @@ Select a task (↑/↓, Enter to run, Esc to clear): lint: vp lint ``` -### Task Specifier {#task-specifier} +### Task Argument {#task-argument} + +The `[task]` argument can be: - `build` — runs the `build` task in the current package - `@my/app#build` — runs the `build` task in a specific package diff --git a/docs/vite/guide/task/getting-started.md b/docs/vite/guide/task/getting-started.md index 615838f52d..7514b25231 100644 --- a/docs/vite/guide/task/getting-started.md +++ b/docs/vite/guide/task/getting-started.md @@ -94,7 +94,7 @@ export default defineConfig({ A task definition can either reference a `package.json` script (by omitting `command`) or specify its own command. You cannot define a command in both places. ::: info -Tasks defined in `vite.config.ts` are cached by default. Plain `package.json` scripts (without a matching task entry) are **not** cached by default. See [Cache Configuration](./config#run-cache) for details. +Tasks defined in `vite.config.ts` are cached by default. Plain `package.json` scripts (without a matching task entry) are **not** cached by default. See [When Is Caching Enabled?](./caching#when-is-caching-enabled) for details. ::: See [Config Reference](./config) for all available task options. @@ -121,65 +121,17 @@ Dependencies can reference tasks in other packages using the `package#task` form dependsOn: ['@my/core#build', '@my/utils#lint'] ``` -## Monorepo Setup +## Running Across Packages -In a monorepo, each package can define its own tasks in its `vite.config.ts`: - -``` -my-project/ -├── pnpm-workspace.yaml -├── packages/ -│ ├── core/ -│ │ ├── package.json # @my/core -│ │ └── vite.config.ts -│ ├── utils/ -│ │ ├── package.json # @my/utils → depends on @my/core -│ │ └── vite.config.ts -│ └── app/ -│ ├── package.json # @my/app → depends on @my/utils -│ └── vite.config.ts -``` - -Use `-r` (recursive) to run a task across all packages: +In a monorepo, use `-r` (recursive) to run a task across all packages: ```bash vp run -r build ``` -``` -~/packages/core$ vp build -✓ built in 28ms - -~/packages/utils$ vp build -✓ built in 21ms - -~/packages/app$ vp build -✓ built in 26ms - ---- -[vp run] 0/3 cache hit (0%). -``` - -The task runner uses your `package.json` dependency graph to determine the order — `@my/core` builds before `@my/utils`, which builds before `@my/app`. This is called **topological ordering** and is applied automatically. - -When combined with `dependsOn`, both types of ordering work together. For example, with `-r` and `dependsOn: ['lint']` on every package's `build` task: - -``` -core#lint → core#build → utils#lint → utils#build → app#lint → app#build -``` - -Each package's `lint` runs before its `build` (explicit dependency), and packages are ordered by their dependency graph (topological). +The task runner automatically orders packages by their `package.json` dependency graph — if `@my/app` depends on `@my/utils` which depends on `@my/core`, they build in that order. Each package's result is cached independently. -Run it again — each package's task is cached independently: - -``` -~/packages/core$ vp build ✓ cache hit, replaying -~/packages/utils$ vp build ✓ cache hit, replaying -~/packages/app$ vp build ✓ cache hit, replaying - ---- -[vp run] 3/3 cache hit (100%), 468ms saved. -``` +See [Running Tasks](./running-tasks) for package selection with `--filter`, `--transitive`, and other options. ## What's Next? diff --git a/docs/vite/guide/task/running-tasks.md b/docs/vite/guide/task/running-tasks.md index 452a423f7a..4645453010 100644 --- a/docs/vite/guide/task/running-tasks.md +++ b/docs/vite/guide/task/running-tasks.md @@ -69,18 +69,14 @@ vp run -w build ## Compound Commands {#compound-commands} -Commands joined with `&&` are split into independently cached sub-tasks: - -```ts [vite.config.ts] -export default defineConfig({ - run: { - tasks: { - check: { - command: 'vp lint && vp build', - }, - }, - }, -}) +Commands joined with `&&` are split into independent sub-tasks, each cached separately when [caching is enabled](./caching#when-is-caching-enabled). This applies to both `vite.config.ts` tasks and `package.json` scripts, where compound commands are common: + +```json [package.json] +{ + "scripts": { + "check": "vp lint && vp build" + } +} ``` ``` From 072e5af9b053b3c2218ef711538f5dc8e497e39b Mon Sep 17 00:00:00 2001 From: branchseer Date: Tue, 10 Mar 2026 17:39:07 +0800 Subject: [PATCH 8/9] docs: add caching and config links to getting started page Co-Authored-By: Claude Opus 4.6 --- docs/vite/guide/task/getting-started.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/vite/guide/task/getting-started.md b/docs/vite/guide/task/getting-started.md index 7514b25231..d765530b46 100644 --- a/docs/vite/guide/task/getting-started.md +++ b/docs/vite/guide/task/getting-started.md @@ -64,7 +64,7 @@ $ vp build ✗ cache miss: 'src/index.ts' modified, executing The task runner automatically tracks which files your command reads. No configuration needed. -The `--cache` flag is a quick way to try caching, but the default behavior may not suit every task — you may need to control which files or environment variables affect the cache. To configure caching properly and enable it permanently, define the task in `vite.config.ts`. +The `--cache` flag is a quick way to try caching, but the default behavior may not suit every task — you may need to control which files or environment variables affect the cache. To configure caching properly and enable it permanently, define the task in `vite.config.ts`. See [Caching](./caching) for how it works and [Config Reference](./config) for all task options. ## Task Definitions {#task-definitions} From 25bf31c1c5b467bf963c2e0757291813b00d8eed Mon Sep 17 00:00:00 2001 From: branchseer Date: Tue, 10 Mar 2026 17:59:08 +0800 Subject: [PATCH 9/9] format --- docs/vite/guide/task/caching.md | 8 ++--- docs/vite/guide/task/cli.md | 44 ++++++++++++------------- docs/vite/guide/task/config.md | 22 ++++++++----- docs/vite/guide/task/getting-started.md | 6 ++-- 4 files changed, 42 insertions(+), 38 deletions(-) diff --git a/docs/vite/guide/task/caching.md b/docs/vite/guide/task/caching.md index b9b85caea8..3f4d698ddc 100644 --- a/docs/vite/guide/task/caching.md +++ b/docs/vite/guide/task/caching.md @@ -38,10 +38,10 @@ A task can set [`cache: false`](./config#cache) to opt out. This cannot be overr The [`run.cache`](./config#run-cache) option in your root `vite.config.ts` controls the default for each category: -| Setting | Default | Effect | -| --- | --- | --- | -| `cache.tasks` | `true` | Cache commands that have a task entry | -| `cache.scripts` | `false` | Cache plain `package.json` scripts | +| Setting | Default | Effect | +| --------------- | ------- | ------------------------------------- | +| `cache.tasks` | `true` | Cache commands that have a task entry | +| `cache.scripts` | `false` | Cache plain `package.json` scripts | Use `--cache` to quickly enable script caching, or set `run.cache.scripts: true` in config to enable it permanently. diff --git a/docs/vite/guide/task/cli.md b/docs/vite/guide/task/cli.md index 52833efe79..613db2eda7 100644 --- a/docs/vite/guide/task/cli.md +++ b/docs/vite/guide/task/cli.md @@ -26,17 +26,17 @@ The `[task]` argument can be: ### Options {#options} -| Flag | Short | Description | -| --- | --- | --- | -| `--recursive` | `-r` | Run in all workspace packages, in topological order | -| `--transitive` | `-t` | Run in the current package and its transitive dependencies | -| `--workspace-root` | `-w` | Run in the workspace root package | -| `--filter ` | `-F` | Select packages by name, directory, or glob (repeatable) | -| `--cache` | — | Enable caching for all tasks and scripts | -| `--no-cache` | — | Disable caching entirely | -| `--ignore-depends-on` | — | Skip explicit `dependsOn` dependencies | -| `--verbose` | `-v` | Show detailed execution summary | -| `--last-details` | — | Display the summary from the last run | +| Flag | Short | Description | +| --------------------- | ----- | ---------------------------------------------------------- | +| `--recursive` | `-r` | Run in all workspace packages, in topological order | +| `--transitive` | `-t` | Run in the current package and its transitive dependencies | +| `--workspace-root` | `-w` | Run in the workspace root package | +| `--filter ` | `-F` | Select packages by name, directory, or glob (repeatable) | +| `--cache` | — | Enable caching for all tasks and scripts | +| `--no-cache` | — | Disable caching entirely | +| `--ignore-depends-on` | — | Skip explicit `dependsOn` dependencies | +| `--verbose` | `-v` | Show detailed execution summary | +| `--last-details` | — | Display the summary from the last run | ### Additional Arguments {#additional-arguments} @@ -48,17 +48,17 @@ vp run test --reporter verbose ### Filter Patterns {#filter-patterns} -| Pattern | Description | -| --- | --- | -| `@my/app` | Exact package name | -| `@my/*` | Glob matching | -| `./packages/app` | By directory | -| `{./packages/app}` | By directory (braced form) | -| `@my/app...` | Package and its dependencies | -| `...@my/core` | Package and its dependents | -| `@my/app^...` | Dependencies only (exclude package itself) | -| `...^@my/core` | Dependents only (exclude package itself) | -| `!@my/utils` | Exclude a package | +| Pattern | Description | +| ------------------ | ------------------------------------------ | +| `@my/app` | Exact package name | +| `@my/*` | Glob matching | +| `./packages/app` | By directory | +| `{./packages/app}` | By directory (braced form) | +| `@my/app...` | Package and its dependencies | +| `...@my/core` | Package and its dependents | +| `@my/app^...` | Dependencies only (exclude package itself) | +| `...^@my/core` | Dependents only (exclude package itself) | +| `!@my/utils` | Exclude a package | Multiple `--filter` flags are combined as a union. Exclusion filters (`!`) are applied after all inclusions. diff --git a/docs/vite/guide/task/config.md b/docs/vite/guide/task/config.md index c61aeed3f8..02070916f7 100644 --- a/docs/vite/guide/task/config.md +++ b/docs/vite/guide/task/config.md @@ -3,14 +3,18 @@ The task runner is configured under the `run` field in your `vite.config.ts`: ```ts [vite.config.ts] -import { defineConfig } from 'vite-plus' +import { defineConfig } from 'vite-plus'; export default defineConfig({ run: { - cache: { /* ... */ }, - tasks: { /* ... */ }, + cache: { + /* ... */ + }, + tasks: { + /* ... */ + }, }, -}) +}); ``` ## `run.cache` {#run-cache} @@ -24,11 +28,11 @@ Global cache settings. Controls whether task results are cached and replayed on export default defineConfig({ run: { cache: { - scripts: true, // Cache package.json scripts (default: false) - tasks: true, // Cache task definitions (default: true) + scripts: true, // Cache package.json scripts (default: false) + tasks: true, // Cache task definitions (default: true) }, }, -}) +}); ``` Shorthands: `cache: true` enables both, `cache: false` disables both. @@ -54,7 +58,7 @@ export default defineConfig({ }, }, }, -}) +}); ``` If a task name matches a script in `package.json`, the script is used automatically when `command` is omitted. See [Getting Started](./getting-started#task-definitions) for details. @@ -97,7 +101,7 @@ tasks: { Dependencies can reference tasks in other packages using the `package#task` format: ```ts -dependsOn: ['@my/core#build', '@my/utils#lint'] +dependsOn: ['@my/core#build', '@my/utils#lint']; ``` See [Task Dependencies](./getting-started#task-dependencies) for details on how explicit and topological dependencies interact. diff --git a/docs/vite/guide/task/getting-started.md b/docs/vite/guide/task/getting-started.md index d765530b46..53de9ee2e7 100644 --- a/docs/vite/guide/task/getting-started.md +++ b/docs/vite/guide/task/getting-started.md @@ -71,7 +71,7 @@ The `--cache` flag is a quick way to try caching, but the default behavior may n Task definitions in `vite.config.ts` enable caching by default and give you more control — dependencies, environment variables, and custom inputs: ```ts [vite.config.ts] -import { defineConfig } from 'vite-plus' +import { defineConfig } from 'vite-plus'; export default defineConfig({ run: { @@ -88,7 +88,7 @@ export default defineConfig({ }, }, }, -}) +}); ``` A task definition can either reference a `package.json` script (by omitting `command`) or specify its own command. You cannot define a command in both places. @@ -118,7 +118,7 @@ Use [`dependsOn`](./config#depends-on) to ensure tasks run in the right order. R Dependencies can reference tasks in other packages using the `package#task` format: ```ts -dependsOn: ['@my/core#build', '@my/utils#lint'] +dependsOn: ['@my/core#build', '@my/utils#lint']; ``` ## Running Across Packages