pnpm 11.2
pnpm 11.2 ships an experimental opt-in into pacquet (the Rust port of pnpm) as the install backend, expands config dependencies to install one level of optionalDependencies (so the esbuild/swc platform-binary pattern works for config deps too), wires up the long-documented pnpm login --scope flag, and surfaces runtime entries (Node.js, Deno, Bun) in pnpm outdated and pnpm update --interactive.
次要更改
Experimental: pacquet as the install backend
Adding @pnpm/pacquet (the Rust port of pnpm) to configDependencies in pnpm-workspace.yaml now delegates the materialization phase of pnpm install to the pacquet binary. pnpm still owns dependency resolution; pacquet only fetches and imports from the freshly-written lockfile. This is an opt-in preview of the Rust install engine — see #11723.
To configure pacquet in a project, run:
pnpm add @pnpm/pacquet --config
You'll see changes in pnpm-workspace.yaml and pnpm-lock.yaml that should be committed. If you experience any issues with pacquet, please let us know in the GitHub issue you create.
optionalDependencies for config dependencies
Config dependencies now resolve and install one level of optionalDependencies declared by the config dependency, with os / cpu / libc platform filtering applied at install time. This unlocks the esbuild/swc-style pattern where a package ships platform-specific binaries via optionalDependencies — a config dependency can now do the same and have the matching binary symlinked next to it in the global virtual store, so require('pkg-platform-arch') from inside the config dependency resolves correctly.
The env lockfile records all platform variants regardless of host platform, so it remains portable across machines. Each entry in a config dependency's optionalDependencies must declare an exact version — ranges and tags are rejected to keep installs reproducible.
pnpm login --scope
The long-documented pnpm login --scope <scope> flag is now implemented. The scope is normalized (a leading @ is added if missing; blank values are ignored) and an @<scope>:registry=<registry> mapping is written to the pnpm auth file alongside the auth token. Subsequent installs of @<scope>/* packages then route to the chosen registry. Previously the documented flag errored with Unknown option: 'scope'. See #11716.
Runtimes in outdated and update --interactive
pnpm outdated and pnpm update --interactive now report Node.js, Deno, and Bun runtimes installed as project dependencies (runtime: specifiers). Previously these were silently skipped.
补丁更改
- Fixed
cafile=<relative-path>in.npmrcbeing read from the wrong directory when pnpm is invoked from a different cwd (e.g.pnpm --dir <project> installfrom a CI wrapper or monorepo script). The path is now resolved against the directory of the.npmrcthat declared it, notprocess.cwd(). Before this fix, the install proceeded without the configured CA and the user only saw TLS errors against a private registry with no log line tying back to the wrongly resolved path #11624. - Fixed
config.registrygetting a trailing slash appended whenregistryis set in.npmrcand noregistries.defaultis provided bypnpm-workspace.yaml. - Fixed global add/update to handle
minimumReleaseAgepolicy violations instead of surfacing an internal resolver guardrail error. - Fixed two crashes with
injectWorkspacePackages: truewhen the lockfile has been pruned (e.g. byturbo prune --docker): aCannot use 'in' operator to search for 'directory' in undefinedfrom peer-dependency-variant injected snapshots whose basepackages:entry had been dropped, and anERR_PNPM_ENOENTonnode_modules/.bin/<tool>afterprepare/postinstallre-imported each injected workspace package. - Fixed
pnpm loginandpnpm logoutignoringregistries.defaultfrompnpm-workspace.yaml#10099. - Fixed the
minimumReleaseAge(publishedBy) maturity shortcut to be inclusive at the cutoff. Previously, abbreviated metadata whosemodifiedfield equalled the cutoff fell off the fast path and triggered a full-metadata re-fetch (or aMISSING_TIMEerror when full metadata wasn't permitted). - Honor
publishConfig.accesswhen publishing packages.
11.2.1
- Mark optional subdependency snapshots of config dependencies with
optional: truein the env lockfile, matching how optional dependencies are recorded elsewhere inpnpm-lock.yaml. Previously, snapshots for the platform-specific subdeps pulled in via a config dep'soptionalDependencieswere written as empty objects. - Fixed
pickRegistryForPackagereturning the wrong registry for an unscopednpm:alias under a scoped local name. A manifest entry like"@private/foo": "npm:lodash@^1"was routing thelodashfetch throughregistries["@private"], even thoughlodashis unscoped. - Don't print
Installing config dependencies...when config dependencies are already installed and nothing needs to be fetched, re-linked, or removed.
11.2.2
- When the install engine is delegated to pacquet via
configDependencies, the user's CLI flags passed topnpm install(e.g.--no-runtime,--prod,--dev,--no-optional,--node-linker,--cpu/--os/--libc,--offline,--prefer-offline) are now forwarded to pacquet'sinstallsubcommand verbatim. Previously pacquet was invoked with a fixed argument list, so flags like--no-runtimewere silently dropped. Flag forwarding is gated on the command beinginstall/i;add,update, anddedupestill don't forward (their flag surface doesn't line up with pacquet'sinstall). - Fixed
pnpm up(andpnpm add/pnpm remove) failing withpacquet_package_manager::outdated_lockfilewhen pacquet is declared inconfigDependencies. pnpm now passes--ignore-manifest-checkto pacquet so its--frozen-lockfilecheck doesn't fire against the (pre-mutation)package.jsonpnpm hasn't written yet #11797.
