vite-plus 1.2.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +4 -0
- package/LICENSE +1 -849
- package/README.md +1 -1
- package/bin/vpx +9 -0
- package/binding/index.cjs +59 -54
- package/binding/index.d.cts +132 -2
- package/dist/{agent-KeDc6vmg.js → agent-D8oxxhVR.js} +7 -9
- package/dist/bin.js +27 -34
- package/dist/{cli-parse-DHE8NrBU.js → cli-parse-aeUeFDlC.js} +2 -3
- package/dist/command-TjS_6y9O.js +1 -0
- package/dist/{command-CguLh2KL.js → command-rY79K5NI.js} +40 -42
- package/dist/{comparison-CmVirWIW-DUGaiYqF.js → comparison-CmVirWIW-UlEf2maz.js} +1 -2
- package/dist/config/bin.js +8 -10
- package/dist/{constants-BW3g7VnD.js → constants-DRUnJ_Dz.js} +4 -6
- package/dist/create/bin.d.ts +4 -8
- package/dist/create/bin.js +64 -68
- package/dist/{define-config-CIlk9scU.js → define-config-ChwJcu5e.js} +6 -9
- package/dist/{define-config-Dq_23Eyr.cjs → define-config-Cv2P6NT2.cjs} +8 -13
- package/dist/{define-config-Bexdd6RZ.d.ts → define-config-rPhYIFSn.d.ts} +1 -11
- package/dist/define-config.cjs +1 -1
- package/dist/define-config.d.ts +1 -1
- package/dist/define-config.js +1 -1
- package/dist/{dist-Bi7ZEK3c.js → dist-Bs0SObNC.js} +77 -149
- package/dist/{dist-Cqz8OtiO.js → dist-CdkMvIiQ.js} +11 -5
- package/dist/dist-zDZV5eEc.js +3 -0
- package/dist/{documentation-DqcZSthV.js → documentation-cv_y0Auv.js} +1 -2
- package/dist/{editor-b1XUwt9v.js → editor-ClL78D8u.js} +1492 -4211
- package/dist/{help-BmKpeOP9.js → help-B03t_iQ4.js} +1 -2
- package/dist/hooks/bin.js +4 -5
- package/dist/{hooks-DhwsWb46.js → hooks-xRcJPc-O.js} +5 -4
- package/dist/index.cjs +2 -3
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/{json-JP24qHUF.js → json-kl84kDyH.js} +9 -18
- package/dist/lint-plugins.cjs +1 -1
- package/dist/migration/bin.js +719 -184
- package/dist/migration/compat/worker.js +4 -6
- package/dist/{oxlint-plugin-config-Dx-ZY2MN.js → oxlint-plugin-config-BVpqYdcC.js} +3 -4
- package/dist/oxlint-plugin.d.ts +0 -2
- package/dist/oxlint-plugin.js +6 -7
- package/dist/{pack-BK38MLVZ.d.ts → pack-ARPFMefW.d.ts} +0 -2
- package/dist/pack-bin.d.ts +1 -3
- package/dist/pack-bin.js +3 -4
- package/dist/pack.d.ts +1 -1
- package/dist/{package-BP16iQby.js → package-DzsomcUD.js} +10 -95
- package/dist/{package-overrides-D1RcXSFl.js → package-overrides-Ci8GXouY.js} +5 -8
- package/dist/picomatch-DEUoj81q.js +1916 -0
- package/dist/{prompts-BGpQtC5z.js → prompts-GL1vj0wk.js} +113 -239
- package/dist/{protocol-D99W10Qi.js → protocol-CkNmY-Mr.js} +1 -2
- package/dist/{report-NhQk8VHb.js → report-DLHO30yZ.js} +2 -2
- package/dist/{resolve-vite-config-x47JetlI.js → resolve-vite-config-Dn5896A4.js} +9 -25
- package/dist/resolve-vite-config-QO6cC0SP.js +1 -0
- package/dist/{rolldown-runtime-CMFfr-1z.js → rolldown-runtime-DegdyBIC.js} +2 -3
- package/dist/script-esm-hooks.d.ts +8 -0
- package/dist/script-esm-hooks.js +24 -0
- package/dist/script-hooks-9Fof5UMY.js +176 -0
- package/dist/script-preload.cjs +468 -0
- package/dist/script-register.d.ts +1 -0
- package/dist/script-register.js +22 -0
- package/dist/script-watch.d.ts +1 -0
- package/dist/script-watch.js +1908 -0
- package/dist/staged/bin.js +81 -2011
- package/dist/sync-versions/bin.js +29 -50
- package/dist/sync-versions/bin.mjs +117 -224
- package/dist/{terminal-MKGAuy-p.js → terminal-BcuPUy-j.js} +1 -2
- package/dist/toolchain.js +36 -10
- package/dist/toolchain.json +36 -10
- package/dist/{tsconfig-C5PnJfW4.js → tsconfig-Do6MAG_f.js} +1 -1
- package/dist/{tsconfig-D2DzAQ_D.js → tsconfig-LE_mAwe_.js} +8 -10
- package/dist/version.d.ts +1 -3
- package/dist/version.js +5 -6
- package/dist/versions.js +5 -5
- package/dist/{vitest-ecosystem-BU0AqZq-.js → vitest-ecosystem-BeEYz-qF.js} +1 -2
- package/dist/{vitest-v5-entry-points-DthU1e_O.js → vitest-v5-entry-points-NyJsFeux.js} +1 -2
- package/dist/vpx-bin.d.ts +1 -0
- package/dist/vpx-bin.js +232 -0
- package/dist/vpx-script-EXgV5QOf.js +434 -0
- package/docs/config/run.md +4 -0
- package/docs/guide/check.md +1 -0
- package/docs/guide/ci.md +13 -3
- package/docs/guide/create.md +34 -0
- package/docs/guide/env.md +27 -13
- package/docs/guide/global-cli.md +52 -0
- package/docs/guide/local-cli.md +4 -4
- package/docs/guide/migrate-rules.md +48 -5
- package/docs/guide/migrate.md +6 -6
- package/docs/guide/package-management.md +19 -2
- package/docs/guide/test.md +1 -1
- package/docs/guide/vitest-v5.md +2 -2
- package/docs/guide/vpx.md +170 -9
- package/package.json +32 -29
- package/dist/command-DaRqSNpP.js +0 -1
- package/dist/dist-CBWGibx8.js +0 -3
- package/dist/resolve-vite-config-CGzlyhGr.js +0 -1
package/docs/guide/global-cli.md
CHANGED
|
@@ -71,6 +71,8 @@ irm https://vite.plus/ps1 | iex
|
|
|
71
71
|
|
|
72
72
|
On Windows, you can instead download and run [`vp-setup.exe`](https://setup.viteplus.dev).
|
|
73
73
|
|
|
74
|
+
The installer uses the latest Node.js LTS to install its JavaScript dependencies. CI integrations can select another compatible version through [`VP_SETUP_NODE_VERSION`](#vp-setup-node-version).
|
|
75
|
+
|
|
74
76
|
After installation, open a new shell and run:
|
|
75
77
|
|
|
76
78
|
```bash
|
|
@@ -105,6 +107,47 @@ These variables control the installer scripts and the standalone Windows install
|
|
|
105
107
|
$env:VP_VERSION = "1.2.3"; irm https://vite.plus/ps1 | iex
|
|
106
108
|
```
|
|
107
109
|
|
|
110
|
+
#### `VP_SETUP_NODE_VERSION`
|
|
111
|
+
|
|
112
|
+
- **Purpose**: Select the Node.js version used to install the global CLI's JavaScript dependencies. CI integrations such as [`setup-vp`](/guide/ci#node-js-during-installation) set this variable to reuse the project's runtime.
|
|
113
|
+
- **Values**: An exact version, a version range, or an alias such as `22.23.1`, `22`, `^22.18.0`, `lts`, or `latest`. The installer resolves the value once to an exact version.
|
|
114
|
+
- **Default**: Unset or empty (use the latest Node.js LTS). Project files, `VP_NODE_VERSION`, session overrides, and the user-level default do not change this default.
|
|
115
|
+
- **Compatibility**: The resolved version must meet the Node.js requirements of both the global CLI and its pinned `pnpm`. Otherwise, the installer uses LTS. An invalid or unresolvable value causes an error.
|
|
116
|
+
- **Scope**: Initial dependency installation only. This variable does not set a project pin, session override, or global default. `vp upgrade` and legacy installers continue to use LTS.
|
|
117
|
+
|
|
118
|
+
#### `VP_SETUP_NODE_VERSION_FILE`
|
|
119
|
+
|
|
120
|
+
- **Purpose**: Optional output file for integrations that need the exact version resolved from `VP_SETUP_NODE_VERSION`.
|
|
121
|
+
- **Contents**: The resolved version, such as `22.23.1`, written after successful dependency installation. If compatibility requires LTS for installation, the file still contains the requested version's resolution.
|
|
122
|
+
- **Default**: Unset (write no file). The installer also writes no file when `VP_SETUP_NODE_VERSION` is unset or empty, or when dependency installation is skipped.
|
|
123
|
+
|
|
124
|
+
`setup-vp` manages this file automatically. Use its Node.js inputs to configure CI jobs.
|
|
125
|
+
|
|
126
|
+
#### `VP_SETUP_SKIP_INSTALL_LOCKFILE`
|
|
127
|
+
|
|
128
|
+
Set this variable to `1` to recover from a lockfile-related error during global CLI installation or `vp upgrade`. All other values, including unset or empty, keep the published installation lockfile enabled.
|
|
129
|
+
|
|
130
|
+
The installer prints a warning and resolves dependencies without reading or recovering the installation lockfile. The requested CLI version stays pinned, but its dependency versions can differ from the release lockfile. Registry, authentication, and proxy settings remain in effect. This option does not affect project installations such as `vp install`.
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
# Retry installation without the bundled lockfile.
|
|
134
|
+
curl -fsSL https://vite.plus | VP_SETUP_SKIP_INSTALL_LOCKFILE=1 bash
|
|
135
|
+
|
|
136
|
+
# Or retry an upgrade, including the currently installed version.
|
|
137
|
+
VP_SETUP_SKIP_INSTALL_LOCKFILE=1 vp upgrade --force
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
```powershell
|
|
141
|
+
$env:VP_SETUP_SKIP_INSTALL_LOCKFILE = "1"
|
|
142
|
+
try {
|
|
143
|
+
irm https://vite.plus/ps1 | iex
|
|
144
|
+
} finally {
|
|
145
|
+
Remove-Item Env:VP_SETUP_SKIP_INSTALL_LOCKFILE
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Keep this override temporary. Later installations and upgrades use the published lockfile again when the variable is unset. To reinstall an affected version with its lockfile, unset the variable and run `vp upgrade <version> --force`.
|
|
150
|
+
|
|
108
151
|
#### `VP_HOME`
|
|
109
152
|
|
|
110
153
|
- **Purpose**: Optional pin for the single-root layout. Set it to an absolute path. Vite+ then puts bin, data, cache, config, and state under that directory. The installed CLI reads the same variable. See [Environment](/guide/env).
|
|
@@ -227,6 +270,7 @@ These variables configure the installed Vite+ CLI. `VP_HOME` (above) also applie
|
|
|
227
270
|
|
|
228
271
|
- **Purpose**: Override Node.js version
|
|
229
272
|
- **Default**: None (auto-detected)
|
|
273
|
+
- **Scope**: Runtime commands. For the installer's dependency installation, use [`VP_SETUP_NODE_VERSION`](#vp-setup-node-version).
|
|
230
274
|
- **Example**:
|
|
231
275
|
```bash
|
|
232
276
|
# Run a command with a specific Node.js version
|
|
@@ -347,6 +391,14 @@ source ~/.config/vite-plus/env.nu
|
|
|
347
391
|
|
|
348
392
|
For a custom `XDG_CONFIG_HOME`, use the absolute path to `<XDG_CONFIG_HOME>/vite-plus/env.nu` as resolved during installation. For an installation under `VP_HOME` or an existing `~/.vite-plus` installation, use `<VP_HOME>/env.nu` or `~/.vite-plus/env.nu` instead. Replace placeholders with actual paths and quote paths containing spaces. Open a new Nushell session and run `vp help` to verify the configuration.
|
|
349
393
|
|
|
394
|
+
#### Nushell version
|
|
395
|
+
|
|
396
|
+
Use Nushell 0.112.1 or later. In Nushell, a custom command or alias can have the same name as a built-in command, for example `def update []`. Nushell reads the Vite+ `env.nu` after your configuration. Thus, `env.nu` must call the built-in commands with the [`%` sigil](https://www.nushell.sh/lang-guide/chapters/custom_commands.html#calling-custom-commands), which Nushell 0.112.1 added.
|
|
397
|
+
|
|
398
|
+
`vp env setup` checks the `nu` on `PATH`. With an earlier Nushell, it writes `env.nu` without the sigil. That `env.nu` still works, but a custom command with the name of a built-in command can stop Nushell at startup with `nu::parser::extra_positional` or a similar parse error. After you upgrade Nushell, run `vp env setup` again.
|
|
399
|
+
|
|
400
|
+
If you have more than one Nushell installation, make sure that the `nu` on `PATH` during `vp env setup` is the Nushell that you start. A Nushell earlier than 0.112.1 cannot parse an `env.nu` that `vp env setup` wrote for a later version.
|
|
401
|
+
|
|
350
402
|
#### `CI`
|
|
351
403
|
|
|
352
404
|
- **Purpose**: Indicates running in CI environment
|
package/docs/guide/local-cli.md
CHANGED
|
@@ -11,19 +11,19 @@ For most of use cases, we recommend to use Vite+ cli to install in a project or
|
|
|
11
11
|
::: code-group
|
|
12
12
|
|
|
13
13
|
```bash [pnpm]
|
|
14
|
-
pnpm
|
|
14
|
+
pnpm create vite-plus
|
|
15
15
|
```
|
|
16
16
|
|
|
17
17
|
```bash [npm]
|
|
18
|
-
|
|
18
|
+
npm create vite-plus@latest
|
|
19
19
|
```
|
|
20
20
|
|
|
21
21
|
```bash [Yarn]
|
|
22
|
-
yarn
|
|
22
|
+
yarn create vite-plus
|
|
23
23
|
```
|
|
24
24
|
|
|
25
25
|
```bash [Bun]
|
|
26
|
-
|
|
26
|
+
bun create vite-plus
|
|
27
27
|
```
|
|
28
28
|
|
|
29
29
|
:::
|
|
@@ -18,11 +18,31 @@ Migration is idempotent: running it again after a successful migration should no
|
|
|
18
18
|
|
|
19
19
|
On a project that already depends on `vite-plus`, `vp migrate` performs an upgrade only: it updates dependencies and package-manager configuration and finalizes imports. It does not touch project setup.
|
|
20
20
|
|
|
21
|
-
- `--full` also runs the setup actions: git hooks, editor config, agent files, ESLint, Prettier, and
|
|
21
|
+
- `--full` also runs the setup actions: git hooks, editor config, agent files, ESLint, Prettier, tsup, and tsx migration, framework shims, the tsconfig `baseUrl` fix, and the Volta to `.node-version` conversion.
|
|
22
22
|
- `--hooks`, `--agent`, and `--editor` opt into a single setup action without `--full`.
|
|
23
23
|
|
|
24
24
|
When a default upgrade skips setup actions that would apply, it prints a hint to run `vp migrate --full`. Fresh (non Vite+) projects always run the full migration.
|
|
25
25
|
|
|
26
|
+
## Oxlint JSON Inheritance
|
|
27
|
+
|
|
28
|
+
When `.oxlintrc.json` or `.oxlintrc.jsonc` uses `extends`, `vp migrate` resolves each file path relative to the config that declares it. It creates shared TypeScript configs and imports them through `lint.extends`, including nested inheritance. Oxlint applies the existing merge order, rule severities, and overrides. Plain `vp lint` uses the migrated rules without a `-c` flag.
|
|
29
|
+
|
|
30
|
+
Migration assumes ESM projects. Shared configs become sibling `.ts` files. Imports from JavaScript and TypeScript configs use `.js` specifiers, which Vite and TypeScript resolve to the generated source files without changing compiler settings. File-level TypeScript pragmas stay before generated imports. Workspace consumers reuse the same generated modules, including the workspace that owns a shared config. Migration defaults stay in each workspace's local `lint` block. Edit these TypeScript files to update shared settings. Original shared JSON and JSONC files remain available to other consumers; edits to those originals do not update the migrated configs.
|
|
31
|
+
|
|
32
|
+
JS-plugin declarations stay in their original config or override. Relative plugin paths become absolute paths at runtime through `fileURLToPath(new URL(..., import.meta.url))`. Explicit inherited `typeAware` and `typeCheck` settings take precedence over migration defaults.
|
|
33
|
+
|
|
34
|
+
Cleanup removes each completed workspace symlink independently. Shared aliases that remain on disk keep their targets and dependencies available.
|
|
35
|
+
|
|
36
|
+
A shared config's owner keeps `env`, `globals`, `settings`, and `ignorePatterns` at the top level of its `lint` block through references to the shared module. Edits to these fields apply to the owner. Other consumers do not inherit them.
|
|
37
|
+
|
|
38
|
+
Generated modules include a source marker. A later migration attempt reuses these modules without replacing user edits, so a preserved consumer can migrate after its conflict is resolved. Existing modules without a matching marker remain conflicts.
|
|
39
|
+
|
|
40
|
+
Failed merges and existing `lint` blocks record a pending marker in the Vite config, so an isolated failure can be retried after the conflict is resolved. A successful merge removes this marker. Completed workspace merges record a completion marker, including configs merged inline. After fixing an unreadable config, run `vp migrate` again to migrate the remaining consumers and remove JSON files that are no longer needed.
|
|
41
|
+
|
|
42
|
+
Shared config imports use literal paths so Vite and TypeScript can resolve filenames containing `#` or `%`. A relative import path containing `?` or a literal backslash requires a manual migration: Vite treats `?` as a query delimiter, and TypeScript treats backslashes as path separators. Migration preserves the JSON config and reports a warning in these cases.
|
|
43
|
+
|
|
44
|
+
Missing files, invalid JSON, inheritance cycles, conflicting output files, and package-local plugins that resolve differently from the Vite config directory produce a warning and leave the original config in place. Configs outside the project or workspace, configs inside `node_modules`, CommonJS Vite configs, and an existing `lint` block require a manual merge. Workspace JSON removal waits until all migration outcomes are known. Preserved JSON consumers retain their transitive dependencies, including configs whose owners migrated successfully. If an inheritance graph cannot be read, workspace JSON files are kept and their owners use shared modules, because the unreadable consumer can reference them. `vp lint` continues to reject string paths in `lint.extends`; path resolution happens only during migration.
|
|
45
|
+
|
|
26
46
|
## Pack Configuration
|
|
27
47
|
|
|
28
48
|
`vp migrate` updates static `pack` objects in `vite.config.*` and exported objects in `tsdown.config.*` for [tsdown 0.23](https://github.com/rolldown/tsdown/releases/tag/v0.23.0). This also runs on existing Vite+ projects without `--full`, including workspace packages. Arrays and direct objects returned by `defineConfig` callbacks are supported. JSON tsdown configs receive the same updates after they merge into `vite.config.ts`.
|
|
@@ -185,6 +205,8 @@ Object-valued nested npm and Bun overrides are preserved: they are user-defined
|
|
|
185
205
|
|
|
186
206
|
Plugin packages (an unscoped name starting with `vite-plugin-` or `unplugin-`, or `vite` in `peerDependencies`/`dependencies`) skip the rewrite even in config files. Only the `vite` specifier is in scope for this rule.
|
|
187
207
|
|
|
208
|
+
`vite/rolldown` and `vite/rolldown/*` are never rewritten, because `vite-plus` does not export those subpaths; they keep resolving through the core alias.
|
|
209
|
+
|
|
188
210
|
`declare module 'vite'` augmentations follow the same rule and are preserved outside config files. Through the core alias they reach the same `@voidzero-dev/vite-plus-core` module whose `UserConfig` types `defineConfig` from `vite-plus`, so they keep working after migration; `vite-plus` itself exports no `UserConfig` symbol, so a rewritten `declare module 'vite-plus'` augmentation would merge with nothing. Extensions aimed at `vite-plus`'s own surface are written against `vite-plus` by hand.
|
|
189
211
|
|
|
190
212
|
### `vitest` and Browser Imports
|
|
@@ -239,8 +261,9 @@ Migration rewrites commands provided by the Vite+ toolchain in `package.json` sc
|
|
|
239
261
|
| `eslint` | `vp lint`, when its optional migration runs |
|
|
240
262
|
| `prettier` | `vp fmt`, when its optional migration runs |
|
|
241
263
|
| `tsup` | `vp pack`, when its optional migration runs |
|
|
264
|
+
| `tsx` | `vpx`, when its optional migration runs |
|
|
242
265
|
|
|
243
|
-
For commands launched through `bunx`, migration preserves `bunx` and its `--bun` flag (keeping the user's chosen runtime) and rewrites only the managed command. This also works when `bunx` follows a command-launcher delimiter such as `run` or `--`:
|
|
266
|
+
For commands launched through `bunx`, migration preserves `bunx` and its `--bun` flag (keeping the user's chosen runtime) and rewrites only the managed command. tsx is the exception: `bunx tsx` becomes `vpx`, and `bunx --bun tsx` keeps tsx (see [tsx to `vpx`](#tsx-to-vpx)). This also works when `bunx` follows a command-launcher delimiter such as `run` or `--`:
|
|
244
267
|
|
|
245
268
|
| Before | After |
|
|
246
269
|
| ------------------------------------------------------- | -------------------------------------------------------- |
|
|
@@ -251,16 +274,36 @@ For commands launched through `bunx`, migration preserves `bunx` and its `--bun`
|
|
|
251
274
|
|
|
252
275
|
Unrelated `bunx` commands and other package-executor forms remain unchanged.
|
|
253
276
|
|
|
277
|
+
### tsx to `vpx`
|
|
278
|
+
|
|
279
|
+
When a `package.json` script, a lint-staged task, or a `#!/usr/bin/env tsx` shebang runs [tsx](https://tsx.is), migration offers to move it to [`vpx`](/guide/vpx), Vite+'s TypeScript script runner. It rewrites scripts and lint-staged tasks in `package.json` and JSON lint-staged files, and `#!/usr/bin/env tsx` shebangs in script files:
|
|
280
|
+
|
|
281
|
+
| Before | After |
|
|
282
|
+
| -------------------------------------------------------------------------- | ------------------------------------------ |
|
|
283
|
+
| `tsx src/seed.ts --rows 10` | `vpx src/seed.ts --rows 10` |
|
|
284
|
+
| `tsx watch --include "*.json" src/a.ts` | `vpx --watch --include "*.json" src/a.ts` |
|
|
285
|
+
| `npx tsx a.ts`, `pnpm exec tsx a.ts`, `pnpm dlx tsx a.ts`, `bunx tsx a.ts` | `vpx a.ts` |
|
|
286
|
+
| `node --import tsx ./a.ts` | `vpx ./a.ts` |
|
|
287
|
+
| `cross-env NODE_ENV=dev tsx a.ts` | `cross-env NODE_ENV=dev vpx a.ts` |
|
|
288
|
+
| `concurrently "tsx watch a.ts" "vp dev"` | `concurrently "vpx --watch a.ts" "vp dev"` |
|
|
289
|
+
|
|
290
|
+
`tsx watch` becomes `vpx --watch`, never `vpx watch`, which runs the npm package `watch`. Node.js options and tsx watch options keep their order, and `--no-cache` is dropped. A quoted command is rewritten only for programs that run it, such as `concurrently`, `nodemon --exec`, `sh -c`, and `cross-env-shell`; a quoted argument of other programs, as in `echo "tsx a.ts"`, is data. `vpx` needs the same Node.js versions as Vite+ itself, and migration already upgrades incompatible runtime pins to them (see [Vitest 5](/guide/vitest-v5)).
|
|
291
|
+
|
|
292
|
+
Migration keeps tsx, with a warning, for a command `vpx` cannot run: `--eval`, `--print`, or `--check`, the REPL, `--test` without files or in watch mode, an entry without a file extension, commands that set `TSX_TSCONFIG_PATH` (pass `--tsconfig` to `vpx` instead) or load tsx through `NODE_OPTIONS`, and commands with pipes, variables, or subshells. It also reads the scripts a command runs, including local `--require` and `--import` modules, and keeps tsx when one does not exist yet, as when an earlier command generates it, and when `vpx` would fail on one: a `require()` of `./a.js` that only tsx resolves to `a.ts`, and, because tsx compiles ES module syntax to CommonJS, a `.cts` file with `import` or `export`, and a file that mixes `import` with `__dirname`, `__filename`, `require()`, or `module.exports` in a package without `"type": "module"`. This check skips globs and scripts after a `cd` or another shell state change, and reads only the files a command names, not the modules they import. It does not look for what else `vpx` handles differently, such as standard decorators, tsconfig `paths` in `require()`, or a tsconfig `module` of `node16` or `nodenext`; `vpx` reports those when the script runs. A package that lists tsx in `dependencies`, `optionalDependencies`, or `peerDependencies` keeps it too, since `vpx` comes from the `vite-plus` devDependency.
|
|
293
|
+
|
|
294
|
+
Migration removes the `tsx` devDependency only when nothing uses tsx anymore: no kept script, no import of `tsx` or its subpaths such as `tsx/esm/api` (in source, build output, or a `package.json` `imports` alias), no shebang, no tool setting such as `--import=tsx` in `package.json` or a JSON or JavaScript config, and no tsx command in CI workflows, git hooks, or shell scripts. The root's dependency stays while any workspace package still uses tsx, and a package's dependency stays while a nested package under it does. When tsx stays, the warning names what still uses it.
|
|
295
|
+
|
|
296
|
+
See [Coming from tsx](/guide/vpx#coming-from-tsx) for the other differences.
|
|
297
|
+
|
|
254
298
|
## Continuous Integration Rules
|
|
255
299
|
|
|
256
300
|
Migration replaces exact `voidzero-dev/setup-vp@v1` references in GitHub Actions workflows and composite actions under `.github` with the latest exact `setup-vp` release known to that Vite+ version. The frozen `v1` tag does not receive new releases. Existing exact versions and commit SHAs are left unchanged.
|
|
257
301
|
|
|
258
302
|
## Node.js Version Rules
|
|
259
303
|
|
|
260
|
-
Migration converts
|
|
304
|
+
Migration converts the Volta `volta.node` pin to `.node-version`, because Vite+ does not read Volta. On an existing Vite+ project this conversion is part of the full setup bucket, so it runs with `vp migrate --full`; fresh migrations run it unconditionally.
|
|
261
305
|
|
|
262
|
-
- `.nvmrc` and Volta
|
|
263
|
-
- When `.nvmrc` is removed, any `actions/setup-node` `node-version-file: .nvmrc` reference in `.github/workflows/*.{yml,yaml}` and composite actions under `.github` (`.github/**/action.{yml,yaml}`) is repointed to `.node-version` so CI does not fail with "node version file ... does not exist".
|
|
306
|
+
- When `.node-version` or `.nvmrc` exists, migration keeps it and skips the Volta conversion. Vite+ reads both files directly (see [Node.js Selection](/guide/env#node-js-selection)).
|
|
264
307
|
|
|
265
308
|
## Package-Manager Rules
|
|
266
309
|
|
package/docs/guide/migrate.md
CHANGED
|
@@ -8,7 +8,7 @@ import { migrationPrompt, upgradePrompt } from '../.vitepress/theme/data/migrati
|
|
|
8
8
|
|
|
9
9
|
## Overview
|
|
10
10
|
|
|
11
|
-
This command is the starting point for consolidating separate Vite, Vitest, Oxlint, Oxfmt, ESLint, Prettier, tsdown, and
|
|
11
|
+
This command is the starting point for consolidating separate Vite, Vitest, Oxlint, Oxfmt, ESLint, Prettier, tsdown, tsup, and tsx setups into Vite+.
|
|
12
12
|
|
|
13
13
|
Use it when you want to take an existing project and move it onto the Vite+ defaults instead of wiring each tool by hand.
|
|
14
14
|
|
|
@@ -95,21 +95,21 @@ Upgrade the [global CLI](./upgrade.md#global-vp) to your target 1.0 release, the
|
|
|
95
95
|
|
|
96
96
|
### Without the Global CLI
|
|
97
97
|
|
|
98
|
-
Use an existing Node.js runtime that satisfies `^22.18.0 || ^24.11.0 || >=26.0.0`. Run the target migrator through your package manager without adding it to the project first. For the `1.
|
|
98
|
+
Use an existing Node.js runtime that satisfies `^22.18.0 || ^24.11.0 || >=26.0.0`. Run the target migrator through your package manager without adding it to the project first. For the `1.4.0` release:
|
|
99
99
|
|
|
100
100
|
::: code-group
|
|
101
101
|
|
|
102
102
|
```bash [pnpm]
|
|
103
|
-
pnpm dlx --package=vite-plus@1.
|
|
103
|
+
pnpm dlx --package=vite-plus@1.4.0 vp migrate --no-interactive
|
|
104
104
|
```
|
|
105
105
|
|
|
106
106
|
```bash [npm]
|
|
107
|
-
npx --package=vite-plus@1.
|
|
107
|
+
npx --package=vite-plus@1.4.0 vp migrate --no-interactive
|
|
108
108
|
```
|
|
109
109
|
|
|
110
110
|
:::
|
|
111
111
|
|
|
112
|
-
Replace `1.
|
|
112
|
+
Replace `1.4.0` with your target release. For a preview, use the version from the PR and pass `--registry=https://registry-bridge.viteplus.dev` to `pnpm` or `npx` before the `vp` command. Keep the version in `--package` explicit so you run the target migrator rather than the old local CLI.
|
|
113
113
|
|
|
114
114
|
After migration, finish dependency installation and validate with the updated local CLI:
|
|
115
115
|
|
|
@@ -151,7 +151,7 @@ View and copy this prompt into your coding agent to upgrade an existing Vite+ 0.
|
|
|
151
151
|
|
|
152
152
|
### Vitest
|
|
153
153
|
|
|
154
|
-
Vitest is automatically migrated through `vp migrate`. `vite-plus` re-exports upstream `vitest@5.0.
|
|
154
|
+
Vitest is automatically migrated through `vp migrate`. `vite-plus` re-exports upstream `vitest@5.0.5` under `vite-plus/test*`, so for node-mode tests a single `vite-plus` install is enough — you no longer need to install `vitest` directly.
|
|
155
155
|
|
|
156
156
|
For browser mode, you can use the base browser runtime (`@vitest/browser`) and Preview provider (`@vitest/browser-preview`) included in `vite-plus`. To use Playwright or WebDriverIO, you also need the opt-in provider (`@vitest/browser-playwright` or `@vitest/browser-webdriverio`) and its framework peer (`playwright` or `webdriverio`).
|
|
157
157
|
|
|
@@ -211,9 +211,10 @@ Use these when you need lower-level package-manager behavior.
|
|
|
211
211
|
- **Dependencies**: `ci`, `prune`, `list`, `rebuild`, `approve-builds`
|
|
212
212
|
- **Patching**: `patch`, `patch-commit`
|
|
213
213
|
- **Packaging and publishing**: `pack`, `version`, `publish`, `stage`, `dist-tag`, `deprecate`
|
|
214
|
-
- **Inspection**: `view`, `search`, `audit`, `fund`, `ping`
|
|
215
|
-
- **Authentication and access**: `login`, `logout`, `whoami`, `token`, `owner`
|
|
214
|
+
- **Inspection**: `view`, `search`, `licenses`, `audit`, `fund`, `ping`
|
|
215
|
+
- **Authentication and access**: `login`, `logout`, `whoami`, `token`, `owner`, `team`
|
|
216
216
|
- **Configuration**: `config`, `cache`
|
|
217
|
+
- **Package manifest**: `pkg get`, `pkg set`, `pkg delete`, `pkg fix`
|
|
217
218
|
|
|
218
219
|
Command support depends on the package manager and its version. Run `vp pm --help` to list commands or `vp pm <command> --help` for available options.
|
|
219
220
|
|
|
@@ -225,6 +226,22 @@ vp pm cache clean -- --force
|
|
|
225
226
|
vp pm audit --json
|
|
226
227
|
```
|
|
227
228
|
|
|
229
|
+
#### Package manifest
|
|
230
|
+
|
|
231
|
+
`vp pm pkg` reads and updates fields in `package.json` using the detected package manager.
|
|
232
|
+
|
|
233
|
+
```bash
|
|
234
|
+
vp pm pkg get name
|
|
235
|
+
vp pm pkg set scripts.build="vite build"
|
|
236
|
+
vp pm pkg set private=true --json
|
|
237
|
+
vp pm pkg delete scripts.build
|
|
238
|
+
vp pm pkg fix
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
npm supports `get`, `set`, and `delete` from 7.20.0 and `fix` from 9.8.0. pnpm supports all four commands from 11.3.0, and Bun supports them through `bun pm pkg` from 1.2.19. Yarn and unsupported versions print a warning and exit successfully without changing the manifest, matching `vp pm patch`.
|
|
242
|
+
|
|
243
|
+
Native behavior is preserved. For example, npm returns JSON from `get`, while pnpm prints a single string value without quotes by default. Use `--json` to request JSON output or to parse values passed to `set` as JSON. Additional native options can be passed after `--`. The corrections made by `fix` depend on the package manager.
|
|
244
|
+
|
|
228
245
|
#### Staged publishing
|
|
229
246
|
|
|
230
247
|
`vp pm stage` exposes [npm's staged publishing](https://docs.npmjs.com/staged-publishing) workflow: a build is uploaded to a staging area (no 2FA, CI-friendly), then a maintainer approves or rejects it from a trusted device (2FA). It adapts to the detected package manager.
|
package/docs/guide/test.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
`vp test` runs tests with [Vitest](https://vitest.dev).
|
|
4
4
|
|
|
5
|
-
Vite+ depends on Vitest `5.0.
|
|
5
|
+
Vite+ depends on Vitest `5.0.5`, which requires Node `^22.18.0 || ^24.11.0 || >=26.0.0`. For existing projects, follow [Upgrade to Vitest 5](./vitest-v5.md) before updating dependencies.
|
|
6
6
|
|
|
7
7
|
`vp test` resolves Vitest from `vite-plus`'s dependencies first, then from your project.
|
|
8
8
|
|
package/docs/guide/vitest-v5.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Upgrade to Vitest 5
|
|
2
2
|
|
|
3
|
-
Vite+ bundles Vitest `5.0.
|
|
3
|
+
Vite+ bundles Vitest `5.0.5`. Use Node `^22.18.0 || ^24.11.0 || >=26.0.0` for the CLI and tests.
|
|
4
4
|
|
|
5
5
|
## Before you migrate
|
|
6
6
|
|
|
@@ -126,7 +126,7 @@ Review calls with benchmark options, imported or reassigned callbacks, callback
|
|
|
126
126
|
|
|
127
127
|
## Entry points and packages
|
|
128
128
|
|
|
129
|
-
Use `vite-plus/test` for assertions and supported runner APIs. Keep coverage providers and `@vitest/ui` at the bundled runner's exact version, `5.0.
|
|
129
|
+
Use `vite-plus/test` for assertions and supported runner APIs. Keep coverage providers and `@vitest/ui` at the bundled runner's exact version, `5.0.5`. Keep `@vitest/web-worker` aligned when your project uses it.
|
|
130
130
|
|
|
131
131
|
| v4 import | v5 import or action |
|
|
132
132
|
| ---------------------------------------- | --------------------------------------------------------------------------- |
|
package/docs/guide/vpx.md
CHANGED
|
@@ -1,25 +1,29 @@
|
|
|
1
1
|
# Running Binaries
|
|
2
2
|
|
|
3
|
-
Use `vpx`, `vp exec`, and `vp dlx` to run binaries without switching between local installs, downloaded packages, and project-specific tools.
|
|
3
|
+
Use `vpx`, `vp exec`, and `vp dlx` to run package binaries and scripts without switching between local installs, downloaded packages, and project-specific tools.
|
|
4
4
|
|
|
5
5
|
## Overview
|
|
6
6
|
|
|
7
|
-
`vpx`
|
|
7
|
+
`vpx` does one of two things, depending on its first argument:
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
- [`vpx <package>`](#running-package-binaries) runs a binary from a local or remote npm package, like `npx`.
|
|
10
|
+
- [`vpx <file>`](#running-scripts) runs a TypeScript or JavaScript file, like `tsx`, and [`vpx --watch <file>`](#watch-mode) runs it again when a file it uses changes, like `tsx watch`.
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
- `vp exec` runs a command from local `node_modules/.bin` directories, falling back to `PATH` if not found
|
|
13
|
-
- `vp dlx` runs a package binary without adding it as a dependency
|
|
12
|
+
The other commands give stricter control over where a binary comes from:
|
|
14
13
|
|
|
15
|
-
|
|
14
|
+
- [`vp exec`](#vp-exec) runs a command from local `node_modules/.bin` directories, falling back to `PATH`.
|
|
15
|
+
- [`vp dlx`](#vp-dlx) runs a package binary without adding it as a dependency.
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
`vpx -v` or `vpx --version` prints the Vite+ version, like `vp --version`. In `package.json` scripts, `vpx` prints the version of the project's `vite-plus` package.
|
|
18
|
+
|
|
19
|
+
## Running Package Binaries
|
|
18
20
|
|
|
19
21
|
```bash
|
|
20
|
-
vpx <pkg[@version]> [args...]
|
|
22
|
+
vpx [options] <pkg[@version]> [args...]
|
|
21
23
|
```
|
|
22
24
|
|
|
25
|
+
`vpx` looks for the binary in local `node_modules/.bin` directories, Vite+-managed global packages, and the system `PATH`, in that order. If none has it, `vpx` downloads the package and runs it via `vp dlx`. With `pkg@version`, `--package/-p`, or `--shell-mode`, it runs via `vp dlx` directly.
|
|
26
|
+
|
|
23
27
|
### Options
|
|
24
28
|
|
|
25
29
|
- `-p, --package <name>` installs one or more additional packages before running the command
|
|
@@ -35,6 +39,163 @@ vpx oxlint@1.85.0 --version
|
|
|
35
39
|
vpx -p cowsay -c 'echo "hi" | cowsay'
|
|
36
40
|
```
|
|
37
41
|
|
|
42
|
+
Package managers and `vp run` put `node_modules/.bin` first on `PATH`, so `package.json` scripts run the `vpx` bin of the project's `vite-plus` package. That bin does not need the global CLI, and it looks only in local `node_modules/.bin` directories. It runs an installed binary directly, as the global `vpx` does, and `pkg@version`, `--package/-p`, or `--shell-mode` via `vp dlx`. A binary that is not installed is an error, so a script never downloads a package by accident:
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
error: vpx: 'eslint' is not installed in node_modules
|
|
46
|
+
note: Add it to devDependencies, or run `vp dlx eslint` to download and run it.
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Running Scripts
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
vpx [--tsconfig <path>] [node options] <file> [args...]
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
`vpx` runs TypeScript and JavaScript files directly, without a `tsx` or `ts-node` dependency. Scripts run on the project's Node.js version, the same one [`vp node`](/guide/env) selects, with the [oxc-node](https://github.com/oxc-project/oxc-node) loader that ships with Vite+.
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
vpx ./scripts/seed.ts --dry-run
|
|
59
|
+
vpx scripts/build.mts
|
|
60
|
+
vpx --watch ./server.ts
|
|
61
|
+
vpx --env-file=.env ./scripts/migrate.ts
|
|
62
|
+
vpx --tsconfig tsconfig.scripts.json ./tools/gen.ts
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Files and Package Names
|
|
66
|
+
|
|
67
|
+
`vpx` runs its argument as a file when it is:
|
|
68
|
+
|
|
69
|
+
- a path (starting with `./`, `../`, or `/`; on Windows also `.\`, `..\`, a drive such as `C:\`, or `\\`) ending in `.ts`, `.mts`, `.cts`, `.tsx`, `.js`, `.mjs`, `.cjs`, or `.jsx`
|
|
70
|
+
- a name with one of those extensions that exists as a file, such as `scripts/seed.ts`
|
|
71
|
+
- a path to a file whose shebang runs `vpx` (see [Shebang Scripts](#shebang-scripts))
|
|
72
|
+
|
|
73
|
+
A missing path, or a missing name with a TypeScript extension, is an error: `vpx` never downloads a package for it. After Node.js options, such as `vpx --inspect seed.ts`, only a missing path is reported by `vpx`; Node.js reports a missing name itself. A name with a JavaScript extension that is not a file, such as `highlight.js`, runs the package of that name.
|
|
74
|
+
|
|
75
|
+
### Supported Syntax
|
|
76
|
+
|
|
77
|
+
- TypeScript syntax that Node.js type stripping rejects: enums, namespaces, parameter properties, and JSX
|
|
78
|
+
- Decorators with `"experimentalDecorators": true`, including `emitDecoratorMetadata`; standard decorators and `accessor` fields are not supported yet
|
|
79
|
+
- tsconfig `paths` for `import`, `.js` imports that point at `.ts` files, and extensionless imports
|
|
80
|
+
- ESM and CommonJS, including `require()` of `.ts` files; a `.cts` file is CommonJS, so it uses `import x = require('...')` and `export =`, and `import`/`export` declarations there fail with an error that suggests renaming the file to `.mts`
|
|
81
|
+
- TypeScript published in `node_modules`
|
|
82
|
+
- tsconfig `jsx`, `jsxImportSource`, `jsxFactory`, `jsxFragmentFactory`, `useDefineForClassFields`, and `verbatimModuleSyntax`; see [JSX](#jsx) and [tsconfig](#tsconfig) for the defaults
|
|
83
|
+
|
|
84
|
+
`vpx` does not type-check. Run [`vp check`](/guide/check) for that.
|
|
85
|
+
|
|
86
|
+
### Options
|
|
87
|
+
|
|
88
|
+
- `--tsconfig <path>` applies one tsconfig to every file (see [tsconfig](#tsconfig))
|
|
89
|
+
- `--watch` runs the file again when a file it uses changes (see [Watch Mode](#watch-mode))
|
|
90
|
+
- Node.js options before the file, such as `--inspect`, `--test`, `--env-file`, `--require`, and `--import`, are passed to Node.js; `--require` and `--import` preloads can be TypeScript too
|
|
91
|
+
- Everything after the file, including `--`, is passed to the script
|
|
92
|
+
|
|
93
|
+
### Shebang Scripts
|
|
94
|
+
|
|
95
|
+
Scripts can use `vpx` as their interpreter. Make the file executable and keep its extension:
|
|
96
|
+
|
|
97
|
+
```ts
|
|
98
|
+
#!/usr/bin/env vpx
|
|
99
|
+
// scripts/release.ts
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### In `package.json` Scripts
|
|
103
|
+
|
|
104
|
+
The `vpx` bin of the `vite-plus` package runs scripts on its own, so `"seed": "vpx ./scripts/seed.ts"` works in `package.json` scripts without the global CLI. It runs them on the Node.js that started it, which inside `vp run` and package manager scripts is the project's version.
|
|
105
|
+
|
|
106
|
+
### Watch Mode
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
vpx --watch [watch options] [node options] <file> [args...]
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
`vpx --watch` runs a file and runs it again when a file it uses changes, like `tsx watch`. It is not Node.js's own watch mode: `vpx` runs oxc-node's watcher (`oxnode watch`) instead, which runs the file with the `vpx` loader.
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
vpx --watch ./src/server.ts --port 3000
|
|
116
|
+
vpx --watch --include "./config/*.json" --exclude "src/**/*.test.ts" ./src/server.ts
|
|
117
|
+
vpx --watch --inspect --clear-screen=false ./src/index.ts
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
It watches every file the script imports or requires (in worker threads too, on Node.js 24 and later), the tsconfig files `vpx` read and the ones they `extends`, the files a failed import looked for, so creating one reruns the script, and `--env-file` files. `node_modules` is not watched unless `--include` names it. Press Return to rerun at once. Ctrl+C stops the script and the watcher; press it again to force kill. `vpx --watch --help` lists the options:
|
|
121
|
+
|
|
122
|
+
- `--include <glob>` also watches matching files, and `--exclude <glob>` never watches them
|
|
123
|
+
- `--clear-screen=false` (or `--no-clear-screen`) keeps the output of earlier runs; the screen is cleared only on a terminal
|
|
124
|
+
- `--kill-signal <signal>` stops the script before a rerun (default `SIGTERM`), and `--kill-timeout <ms>` force kills it after that long (default 5000)
|
|
125
|
+
- `--rerun-on-enter=false` (or `--no-rerun-on-enter`) leaves stdin to the script
|
|
126
|
+
- `--poll[=<ms>]` polls files instead of using file system events, for Docker, WSL, and network drives
|
|
127
|
+
- `--tsconfig <path>` applies one tsconfig to every file, as for `vpx <file>`
|
|
128
|
+
|
|
129
|
+
`tsx watch`'s `--ignore` and `--no-cache` and its `CHOKIDAR_USEPOLLING` variable work too (`--no-cache` does nothing: `vpx` has no transform cache), and so do the Node.js watch mode options `--watch-preserve-output` and `--watch-kill-signal`, so scripts written for `tsx watch` or `node --watch` move over. `--watch-path`, which would start Node.js's watch mode, is an error that points to `--include`, and so are `--test`, `--eval`, and other options that run no file. Other Node.js options go before the file.
|
|
130
|
+
|
|
131
|
+
### tsconfig
|
|
132
|
+
|
|
133
|
+
`vpx` reads compiler options from a tsconfig but does not type-check with it. Each file uses the nearest `tsconfig.json` above it that includes it through `files`, `include`, `exclude`, or project `references`, as `tsc` does, and `extends` is followed. Files in `node_modules` use no tsconfig, and neither does a file that no tsconfig includes, so it gets the defaults below. Such a file still resolves `paths` aliases through the nearest `tsconfig.json` above it, as tsx does: with a root tsconfig whose `include` is `["src"]`, a script in `scripts/` can import the same aliases as `src/`. Because the config depends on the file's location, not on the working directory, `vpx` compiles a file the same way wherever it runs from.
|
|
134
|
+
|
|
135
|
+
`--tsconfig <path>` applies one config to every file instead, including files that config does not include. Without `--tsconfig`, an `OXC_TSCONFIG_PATH` or `TS_NODE_PROJECT` environment variable does the same. If it names a file that does not exist, or a tsconfig fails to parse, `vpx` prints a warning and runs without that config.
|
|
136
|
+
|
|
137
|
+
A file that no tsconfig applies to runs as if its `compilerOptions` were empty:
|
|
138
|
+
|
|
139
|
+
| Option | Without a tsconfig |
|
|
140
|
+
| --------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
141
|
+
| `module` | The module format comes from `package.json` `"type"`: ESM with `"module"`, CommonJS otherwise. `.mts` is always ESM and `.cts` always CommonJS. With a tsconfig `module` of `node16`, `node18`, `nodenext`, `es2015`, or later, `.ts` and `.tsx` files run as ESM regardless of `"type"`; for the `node*` values, `tsc` and tsx follow `"type"` instead. |
|
|
142
|
+
| `paths`, `baseUrl` | None. Imports resolve as in Node.js, plus `.js` to `.ts` or `.tsx`, `.mjs` to `.mts`, `.cjs` to `.cts`, and extensionless imports. |
|
|
143
|
+
| `useDefineForClassFields` | `true`: class fields have `[[Define]]` semantics and run natively, as with a `target` of `ES2022` or later. A lower `target` switches to `[[Set]]` semantics, as in `tsc`. |
|
|
144
|
+
| `experimentalDecorators` | `false`: a decorator fails with an error that asks for this option. |
|
|
145
|
+
| `emitDecoratorMetadata` | `false`. |
|
|
146
|
+
| `jsx`, `jsxImportSource` | The automatic runtime, importing `react/jsx-runtime` (see [JSX](#jsx)). |
|
|
147
|
+
| `verbatimModuleSyntax` | `false`: imports whose bindings are unused at runtime are removed, with their side effects. |
|
|
148
|
+
| `rewriteRelativeImportExtensions` | `false`. `./file.ts` imports work either way. |
|
|
149
|
+
|
|
150
|
+
Types are removed, and enums, namespaces, and parameter properties are compiled, whatever the tsconfig says. `strict`, `lib`, and other type-checking options have no effect, and `target` only changes the class field default.
|
|
151
|
+
|
|
152
|
+
### JSX
|
|
153
|
+
|
|
154
|
+
`.jsx` and `.tsx` files compile to calls into a JSX runtime, React's by default. Install the runtime they use, `react` or the package named by `jsxImportSource`; Vite+ does not ship one. tsconfig options select the runtime:
|
|
155
|
+
|
|
156
|
+
| tsconfig `jsx` | Output |
|
|
157
|
+
| ------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------- |
|
|
158
|
+
| not set, or `"react-jsx"` | The automatic runtime: `jsx()` and `jsxs()` from `<jsxImportSource>/jsx-runtime`, with `jsxImportSource` defaulting to `react` |
|
|
159
|
+
| `"react-jsxdev"` | The development runtime: `jsxDEV()` from `<jsxImportSource>/jsx-dev-runtime`, with the file name, line, and column of each element |
|
|
160
|
+
| `"react"` | The classic runtime: `React.createElement()`, or `jsxFactory`, with fragments as `React.Fragment`, or `jsxFragmentFactory` |
|
|
161
|
+
| `"preserve"`, `"react-native"` | The automatic runtime, because Node.js cannot run JSX |
|
|
162
|
+
|
|
163
|
+
A classic factory that the file imports, such as `import { h, Fragment } from 'my-jsx'`, is kept even though only JSX uses it.
|
|
164
|
+
|
|
165
|
+
Pragma comments override the tsconfig for that file:
|
|
166
|
+
|
|
167
|
+
```tsx
|
|
168
|
+
/** @jsxImportSource my-jsx */
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
```tsx
|
|
172
|
+
/** @jsxRuntime classic */
|
|
173
|
+
/** @jsx h */
|
|
174
|
+
/** @jsxFrag Fragment */
|
|
175
|
+
import { h, Fragment } from 'my-jsx';
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
When a file has both `@jsx` and `@jsxImportSource`, `@jsxImportSource` selects the automatic runtime and `@jsx` is ignored. Pragmas are read from every comment in the file, so prose such as `// @jsxImportSource is set above` in an ordinary comment changes the runtime too.
|
|
179
|
+
|
|
180
|
+
A `.jsx` file gets a tsconfig's JSX options only when that tsconfig sets `"allowJs": true`, as in `tsc` and tsx. Otherwise it uses the defaults above.
|
|
181
|
+
|
|
182
|
+
JSX that depends on a compiler plugin is not supported. `vpx` compiles JSX only into calls to a runtime's `jsx()`, `jsxs()`, and `jsxDEV()` exports or to a classic factory. A setup that relies on a Babel or bundler plugin to transform JSX, usually with `"jsx": "preserve"`, fails at runtime or loses what that plugin adds.
|
|
183
|
+
|
|
184
|
+
### Coming from tsx
|
|
185
|
+
|
|
186
|
+
`vp migrate` rewrites tsx commands in `package.json` scripts to `vpx` and removes the `tsx` devDependency once nothing uses it; see [tsx to `vpx`](/guide/migrate-rules#tsx-to-vpx). Most scripts that run with tsx run with `vpx` unchanged. These differences can need a change:
|
|
187
|
+
|
|
188
|
+
- **JSX default**: without a tsconfig `jsx` option, tsx compiles JSX to `React.createElement()`, which needs `React` in scope, while `vpx` uses the automatic runtime. Set `"jsx": "react"` to keep the classic output. Because of its default, tsx also ignores a lone `/** @jsxImportSource … */` comment unless the file has `/** @jsxRuntime automatic */` or the tsconfig sets `"jsx": "react-jsx"`; `vpx` applies the comment on its own.
|
|
189
|
+
- **`.cts` files with `import` or `export`**: tsx compiles them to CommonJS, and `vpx` reports an error. Rename the file to `.mts`, or write it with `import x = require()` and `export =`.
|
|
190
|
+
- **`import` in a CommonJS package**: in a package without `"type": "module"`, tsx compiles a `.ts` or `.js` file that uses `import`, `export`, or `import.meta` to CommonJS, so `__filename`, `__dirname`, and `require` still work. `vpx` runs such a file as an ES module, as Node.js does, so they are not defined, and a default import of it from an ES module gets its default export rather than the whole module. Use `import.meta.filename`, `import.meta.dirname`, and `createRequire(import.meta.url)` instead.
|
|
191
|
+
- **`require()` resolution**: tsx maps `require('./a.js')` to `a.ts` and applies tsconfig `paths` to `require()`. `vpx` resolves `require()` as Node.js does, so write the `.ts` extension, and use `paths` aliases only with `import`.
|
|
192
|
+
- **Signals**: tsx turns `SIGINT` and `SIGTERM` into exit codes 130 and 143 and runs `process.on('exit')` handlers first. Under `vpx` the signal ends the script, as it does under Node.js, so clean up in a `process.on('SIGINT')` or `process.on('SIGTERM')` handler.
|
|
193
|
+
- **Node.js version**: `vpx` needs Node.js `^22.18.0 || ^24.11.0 || >=26.0.0`, while tsx also runs on older releases.
|
|
194
|
+
- **Watch mode**: `tsx watch` becomes `vpx --watch`, which takes tsx watch's options (see [Watch Mode](#watch-mode)). It also reruns the script on tsconfig edits and when a file a failed import looked for is created, which tsx watch misses.
|
|
195
|
+
- **Eval, REPL, and `--check`**: `vpx --eval`, the REPL, and `vpx --check` do not transform TypeScript.
|
|
196
|
+
- **`node --import tsx`**: `vpx` has no equivalent for tools that must start `node` themselves.
|
|
197
|
+
- **Other loaders**: remove `--import tsx` from `NODE_OPTIONS`. Two loaders registered together compete for the same files.
|
|
198
|
+
|
|
38
199
|
## `vp exec`
|
|
39
200
|
|
|
40
201
|
Use `vp exec` to run tools already installed in your project or available in your environment.
|