Repository navigation
perf(pm): skip the npm --version spawn in npm projects - #3259
Conversation
In a project that uses npm, `vp run`, `vp list`, `vp outdated`, `vp install`, and the other package-manager commands first ran `npm --version` to learn the version of the npm on PATH. That starts Node.js one more time for every command. Two paths ran it: the default resolution (`resolve_npm_from_path`, which `vp run` also uses) and the system-first shim mode (`system_package_manager` in the global CLI). `npm --version` prints the `version` field of npm's own package.json. The npm on PATH normally links into its package (`bin/npm` -> `lib/node_modules/npm/bin/npm-cli.js`), so both paths read that manifest now. If the nearest package.json within four parents does not belong to npm (for example a version-manager shim, Corepack, or Windows `npm.cmd`), they run `npm --version` as before. The manifest belongs to the npm on PATH, not to the npm that ships with Node.js, so an npm in a separate global prefix keeps its own version. npm does not switch versions per project, so the value matches `npm --version`. pnpm, yarn, and bun do not change: `vp` resolves their version itself and runs `--version` only in system-first mode, and pnpm and yarn can switch to the version that the project selects before they answer. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
68dbcc6 to
fbc1817
Compare
|
CI flaky issue has been fixed in main branch, you can merge commit from main. 😭 |
|
This was a design left by me actually, I'll share some context:
I originally designed a Also, the current |
|
@liangmiQwQ I don't think this PR changes which npm version So in short, this PR is to imitate what |
|
@magurotuna Let me take care of the flaky ci 😢 |
Oh! I previously thought you are reading projects' package.json, sorry for misunderstanding! |
Vite+ 1.5 adds an official Homebrew tap, runs TypeScript through Node.js with `node --import vite-plus/register`, and lets `vp migrate` move `oxnode` and transpile-only `ts-node` scripts to `vpx`. ### Features - Install `vp` from the official Homebrew tap on macOS and glibc Linux ([docs](https://viteplus.dev/guide/homebrew)) ([#2740](#2740)), by @fengmk2: ```bash brew tap voidzero-dev/vite-plus https://github.com/voidzero-dev/vite-plus brew install voidzero-dev/vite-plus/vp ``` - `node --import vite-plus/register` runs TypeScript with the same loader as `vpx`, so tools that start Node.js themselves, such as the Node.js test runner, AVA, or a `NODE_OPTIONS` setting, can run TypeScript files ([docs](https://viteplus.dev/guide/vpx#using-node-js-directly)) ([#3208](#3208)), by @fengmk2. - `vp migrate` moves `oxnode` commands and transpile-only `ts-node` commands to `vpx`, and moves their Node.js preloads and literal `NODE_OPTIONS` values to `vite-plus/register`. `ts-node` commands that type-check stay unchanged with a warning, and the `ts-node` dependency is removed only when nothing still uses it. A project already on Vite+ gets this migration with `vp migrate --full` ([docs](https://viteplus.dev/guide/migrate-rules#oxnode-to-vpx)) ([#3209](#3209), [#3210](#3210)), by @fengmk2. - `vp migrate` warns when it finds Rollup, Rolldown, or Jest dependencies with matching configuration, and explains how to move them to Vite, tsdown, or Vitest. The warnings show during the first migration, or with `vp migrate --full` in a project already on Vite+ ([#3275](#3275)), by @KTrain5169 and @fengmk2. - `vite-plus` exports `resolveConfigFromFile(configFile, options?)`, which resolves a config relative to the config file's directory instead of `process.cwd()`, so editor plugins with several workspace folders load the files of the right project ([#3249](#3249)), by @leaysgur and @fengmk2. - Security: the CLI ships `minimatch@11.0.4`, which fixes a denial of service through glob pattern amplification ([GHSA-g3hv-75wg-m249](GHSA-g3hv-75wg-m249), medium), and `zstd@0.13.4`, which fixes [RUSTSEC-2026-0391](https://rustsec.org/advisories/RUSTSEC-2026-0391), [RUSTSEC-2026-0398](https://rustsec.org/advisories/RUSTSEC-2026-0398), and [RUSTSEC-2026-0403](https://rustsec.org/advisories/RUSTSEC-2026-0403) ([#3328](#3328), [#3331](#3331)), by @renovate[bot] and @wan9chi. - Upgrade the bundled tools ([#3205](#3205), [#3236](#3236), [#3261](#3261), [#3206](#3206), [#3330](#3330), [#3338](#3338)), by @voidzero-guard[bot] and @fengmk2: - `rolldown@1.2.15` to `rolldown@1.2.16`, with `experimentalInlineCommonChunks` in dev mode and no crash when the working directory was deleted. - `tsdown@0.23.1` to `tsdown@0.23.4`: `vp pack --env-file` can be repeated to load several env files, the config has a JSON schema, and `?inline` CSS imported from dependencies is inlined. - `vitest@5.0.5` to `vitest@5.1.0`, with `--last-failed` and `--since-last-run`, fake timers for `node:timers`, and interactive review of failed snapshots. Browser mode now uses port 23315 by default. - `oxlint@1.89.0` to `oxlint@1.91.0` and `oxlint-tsgolint@7.0.2004` to `oxlint-tsgolint@7.0.2005`, with the new type-aware rule `typescript/no-unsafe-enum-assignment`, wider checks in rules such as `array-callback-return`, `no-useless-concat`, and `no-control-regex`, and two rules moved into the `suspicious` category. - `oxfmt@0.74.0` to `oxfmt@0.76.0`, with a new HTML formatter and JavaScript and TypeScript fixes for parentheses, array layout, and line width with wide characters. - The new oxlint and oxfmt versions can flag code that passed before. If your CI runs `vp check`, run `vp fmt` after upgrading. - `vpx` and `vite-plus/register` run on `oxc-node@1.0.1`, which resolves a `.jsx` specifier to its `.tsx` or `.ts` source. ### Fixes & Enhancements - `vp create` into a target path that is a symbolic link removes only the link after confirmation, instead of deleting the contents of the linked directory, and the overwrite prompt names symbolic links and files ([#2418](#2418)), by @leslieeilsel and @fengmk2. - `vp implode` removes only directories and shims that it can verify as Vite+ installations, and refuses the home directory, its parents, and filesystem roots even with `--yes`, so a `VP_HOME` that points at another directory cannot delete unrelated files ([#3228](#3228)), by @jong-kyung. - `vp run` starts faster in workspaces whose tasks share cache `input` and `output` patterns, because each pattern is parsed once. In a 138-package workspace this saves about 2 seconds of CPU on every run ([vite-task#887](voidzero-dev/vite-task#887), [vite-task#890](voidzero-dev/vite-task#890)), by @jasonkuhrt and @wan9chi. - `vp run` and package-manager commands in npm projects start about 110 ms sooner, because `vp` reads the npm version from npm's `package.json` instead of running `npm --version` ([#3259](#3259)), by @magurotuna. - `vp migrate` checks Vitest prerequisites faster in workspaces, because it parses each lockfile once ([#3212](#3212)), by @jong-kyung. - The installer and `vp upgrade` install the global CLI's dependencies with the Node.js version that the release pins (24.22.2 for this release), instead of the latest LTS ([docs](https://viteplus.dev/guide/ci#node-js-during-installation)) ([#3269](#3269)), by @fengmk2. - The Node.js `latest` alias in `vp env use`, `vp env default`, `vp env pin`, `vp env install`, and `.nvmrc` resolves to the newest stable release instead of a `27.0.0-alpha` build, and `vp env list-remote` marks that stable release as latest ([#3335](#3335)), by @voidzero-bot[bot] and @fengmk2. - `VP_NODE_VERSION=22` and other partial versions work for project commands such as `vp build`, `vp run`, and `vp list`, instead of failing with a 404 download error ([#3341](#3341)), by @jong-kyung. - Two `vp install -g` commands that run at the same time no longer delete each other's active package, and a command that starts while a package manager is being installed no longer runs its shim before the shim is executable ([#3185](#3185), [#3248](#3248)), by @jong-kyung. - `vp config` waits and retries when another linked git worktree holds the shared git config lock, so a `prepare` script no longer fails when two worktrees install at the same time ([#3199](#3199)), by @naokihaba. - `vp env doctor` reports Node.js resolution failures, unreadable config, a failing system `node`, and missing shims as errors and exits with code 1. When it finds only warnings, the summary says `Some warnings found` instead of `All checks passed` ([#3215](#3215), [#3222](#3222)), by @liangmiQwQ. - Nushell completions for `vp` and `vpr` use the named completer input, so Nushell 0.116 shows no deprecation warning, and they fall back to file completion when fish is not installed. Run `vp env setup --refresh` to regenerate `env.nu` ([#3267](#3267), [#3276](#3276)), by @naokihaba. - `vp migrate` removes the `tsx` dependency even when a comment still contains a `tsx` command or code fence, and keeps it for JSDoc type imports that need it ([#3299](#3299)), by @voidzero-bot[bot] and @fengmk2. - The `prefer-vite-plus-imports` lint rule and its autofix leave the `vite` and `vitest` imports that `vp migrate` keeps, such as `vitest` imports in a package that lists `vitest` in `peerDependencies`, so `vp lint --fix` no longer breaks the package for its plain Vitest users ([#3192](#3192)), by @Dunqing. - Generated Zed settings no longer force `typeAware` and `unusedDisableDirectives`, so editor diagnostics follow the `lint.options` in `vite.config.ts`. Existing editor settings stay unchanged ([#2357](#2357)), by @pweyck. - `vp dlx` with npm runs the right executable for scoped packages such as `@angular/cli` ([#3229](#3229)), by @jong-kyung. - `vp outdated -r` in npm projects checks the workspaces instead of transitive dependencies, and requires npm 7.14.0 or later ([#3240](#3240)), by @jong-kyung. - Dependency filters such as `--prod` and `--dev` work with npm 6, and filters that npm 6 cannot apply are rejected instead of passed through ([#3251](#3251)), by @jong-kyung. - Package-manager commands that the selected version does not have, such as `vp pm stage` before npm 11.15.0, are skipped with a warning. Unsupported `pnpm dlx` and `pnpm pack` options, and project-only flags on managed global commands such as `vp install -g`, are rejected instead of silently ignored ([#3286](#3286), [#3285](#3285)), by @jong-kyung. - `vp toolchain -g` is short for `vp toolchain --global` ([#3189](#3189)), by @jong-kyung. - On Linux and macOS, programs in tasks with automatic file-access tracking no longer abort when they call `exec` with an empty path or `execl` with 32 or more arguments ([vite-task#896](voidzero-dev/vite-task#896), [vite-task#865](voidzero-dev/vite-task#865)), by @wan9chi and @tlq5l. ### Refactor - Remove the test-only package download wrapper ([#3224](#3224)), by @jong-kyung. ### Docs - Explain that `vp check` stops at formatting failures, and that `vp check` flags go before file paths ([#3262](#3262)), by @SaKaNa-Y. - Show how to align an existing `vite` dependency with its override during a manual npm installation, to avoid `EOVERRIDE` ([#3157](#3157)), by @SaKaNa-Y. - Explain how environment variable prefixes such as `FOO=bar command` work in task commands on every platform ([#3161](#3161)), by @tartelettie. - Restore the `/vp-setup` redirect and the redirects for moved guide pages ([#3271](#3271)), by @fengmk2. - Align the labels of "See [...]" section links with their target titles ([#3231](#3231)), by @yamaurakazuto. ### Chore - Bump vite-task to `40cb9ca`; its user-facing changes are listed above ([#3246](#3246), [#3280](#3280)), by @wan9chi. - Keep CI working on the Node.js 26 LTS and Ubuntu 24.04, cap job runtimes, reduce Node.js downloads, avoid upgrade build and snapshot download timeouts, pin Nushell, and restore Namespace Linux runners ([#3198](#3198), [#3258](#3258), [#3266](#3266), [#3268](#3268), [#3303](#3303), [#3309](#3309), [#3320](#3320), [#3332](#3332)), by @fengmk2 and @wan9chi. - Add automated issue triage ([#3253](#3253), [#3260](#3260)), by @Boshen and @fengmk2. - Run the upstream dependency upgrade with Kimi K3.1 Pro and report its timeouts ([#3314](#3314), [#3304](#3304)), by @Brooooooklyn and @wan9chi. - Stabilize and trim tests: rerun ESLint and Prettier migration fixtures with `--full`, stabilize pnpm setup and Bun snapshots, update the tiptap ecosystem pin, use a recorded package in the install shortcut case, and remove duplicate `devEngines` parse tests ([#3193](#3193), [#3196](#3196), [#3242](#3242), [#3305](#3305), [#3301](#3301)), by @liangmiQwQ, @fengmk2, @wan9chi, and @Brooooooklyn. - Update Rust crates, synchronize workspace dependency requirements, and stop installing `dprint` and `taplo` in `just init` ([#3234](#3234), [#3310](#3310), [#3250](#3250)), by @renovate[bot], @leaysgur, and @fengmk2. - Refine contributor guidance: the release-manager skill, isolated CLI bootstrap checks in `AGENTS.md`, and the Rolldown exports in the CLI bundling notes ([#3207](#3207), [#3238](#3238), [#3316](#3316)), by @fengmk2 and @liangmiQwQ. ### Bundled Versions | Tool | Version | Source | Changelog | | --------------- | ---------- | ---------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | vite | `8.3.5` | [`981f07f`](vitejs/vite@981f07f) | unchanged | | rolldown | `1.2.16` | [`de6facf`](rolldown/rolldown@de6facf) | [1.2.16](https://github.com/rolldown/rolldown/releases/tag/v1.2.16) | | oxc-node | `1.0.1` | [`7ff14c3`](oxc-project/oxc-node@7ff14c3) | [1.0.1](https://github.com/oxc-project/oxc-node/releases/tag/v1.0.1) | | tsdown | `0.23.4` | [npm](https://npmx.dev/package/tsdown/v/0.23.4) | [0.23.2](https://github.com/rolldown/tsdown/releases/tag/v0.23.2), [0.23.3](https://github.com/rolldown/tsdown/releases/tag/v0.23.3), [0.23.4](https://github.com/rolldown/tsdown/releases/tag/v0.23.4) | | vitest | `5.1.0` | [npm](https://npmx.dev/package/vitest/v/5.1.0) | [5.1.0](https://github.com/vitest-dev/vitest/releases/tag/v5.1.0) | | oxlint | `1.91.0` | [npm](https://npmx.dev/package/oxlint/v/1.91.0) | [1.90.0](https://github.com/oxc-project/oxc/releases/tag/oxlint_v1.90.0), [1.91.0](https://github.com/oxc-project/oxc/releases/tag/oxlint_v1.91.0) | | oxlint-tsgolint | `7.0.2005` | [npm](https://npmx.dev/package/oxlint-tsgolint/v/7.0.2005) | [7.0.2005](https://github.com/oxc-project/tsgolint/releases/tag/v7.0.2005) | | oxfmt | `0.76.0` | [npm](https://npmx.dev/package/oxfmt/v/0.76.0) | [0.75.0](https://github.com/oxc-project/oxc/releases/tag/oxfmt_v0.75.0), [0.76.0](https://github.com/oxc-project/oxc/releases/tag/oxfmt_v0.76.0) | ### Upgrade ```bash vp upgrade ``` ### New Contributors @yamaurakazuto, @tartelettie, @pweyck, @jasonkuhrt **Full Changelog**: v1.4.0...v1.5.0 --- Merging this PR will trigger the release workflow. --------- Co-authored-by: voidzero-guard[bot] <278573678+voidzero-guard[bot]@users.noreply.github.com> Co-authored-by: MK (fengmk2) <fengmk2@gmail.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Summary
This PR saves about 110 ms on every
vp runand every package-manager command (vp install,vp add,vp list,vp outdated, and others) in npm projects by makingvpread the npm version from npm'spackage.jsoninstead of runningnpm --version.Benchmark
vp run noopvp listnoopis a script that runsnode -e 0. Mean of 30 runs on:Approach
vpneeds the npm version to build the right command line and thenpm_config_user_agentfor scripts. It rannpm --versionfor this, which starts Node.js and loads npm only to print theversionfield of npm's ownpackage.json. Reading that file directly skips the process.If the npm on
PATHdoes not resolve into npm's package (for example, a version-manager shim, Corepack, ornpm.cmdon Windows),vpstill runsnpm --version.This PR only affects npm cases. pnpm and yarn leave room for a similar speedup: in system-first mode,
vprunspnpm --versionoryarn --version, and the JavaScript builds (pnpm 11 and earlier, and yarn) answer slowly. However, pnpm and yarn can switch to the version that the project selects, so reading theirpackage.jsonwould not be correct. This is left for a follow-up.