Passa al contenuto principale

pnpm 11.21-11.22

· 8 minuti di lettura
Zoltan Kochan
Lead maintainer of pnpm

pnpm 11.21 and 11.22 teach pnpm install to update the lockfile in place for most everyday changes instead of re-resolving the whole dependency graph, stop recording SSH URLs that break installs on CI, make global installs switch over atomically and global interactive updates select whole install groups, add pnpm cache path, and take away a project's ability to relocate pnpm's machine-level state through pnpm-workspace.yaml.

Minor Changes

A project can no longer relocate machine-level state

A repository you clone should not decide where pnpm keeps your credentials, its own installation, or the registry it downloads its next version from. Since v11.22.0, bin, configDir, dir, globalBinDir, globalDir, npmrcAuthFile, pnpmHomeDir, stateDir, userconfig, and workspaceDir are ignored in a project's pnpm-workspace.yaml, with a warning; cacheDir and storeDir are unaffected (#13629).

Two companions keep the rule visible: pnpm config set now refuses to write such a setting into pnpm-workspace.yaml (ERR_PNPM_CONFIG_SET_NOT_A_PROJECT_SETTING, naming where the setting belongs), and the --config. spellings of these flags no longer take effect through the project-manifest merge — they were never a supported way to set those directories.

A warning when global commands run under sudo

pnpm keeps global packages and configuration in the invoking user's home directory, so running pnpm setup, pnpm self-update, or pnpm add --global through sudo silently operates on the root user's home instead of yours. Since v11.21.0 these commands print a warning when run as root; in pnpm v12 they fail with ERR_PNPM_SUDO_NOT_SUPPORTED. Read-only global commands such as pnpm bin --global are unaffected.

Interactive global updates select install groups

pnpm update --global --interactive now presents each isolated install group as one selectable item. Packages that share a global installation resolve against each other, so they update together as a unit; the update is then restricted to the groups you selected.

pnpm cache path

The new pnpm cache path command prints the directory pnpm uses for its metadata cache. CI setups can persist that directory — including the lockfile verification log, which lets a job skip re-checking an unchanged lockfile against the configured supply-chain policies. pnpm store prune also no longer deletes that log. See Continuous Integration for the recipe.

Pruning stale release-age exclusions

The new minimumReleaseAgeExcludePrune setting makes pnpm add, pnpm update, and pnpm remove drop minimumReleaseAgeExclude entries that the freshly written lockfile no longer resolves, so the exclusion list shrinks back as the pinned versions age out. Name patterns (@myorg/*) are always kept.

In the same spirit, cleanupUnusedCatalogs is renamed to catalogPrune, so catalog pruning and release-age exclude pruning use one vocabulary. The old spelling keeps working; when both are set, catalogPrune wins.

Faster runtime resolution

Resolving a Node.js runtime version (devEngines.runtime / runtime: specifiers) is much faster: per-version release metadata is cached after its signature is verified, and an exact stable version such as runtime:22.23.2 no longer downloads the Node.js release index. A pinned runtime whose metadata was fetched once resolves without any network access, which removes the noticeable delay on the first node invocation in a project pinning an already-downloaded runtime (#13899).

Patch Changes

Most everyday changes no longer re-resolve the dependency graph

Previously, many routine edits forced pnpm install to re-resolve the whole dependency graph, even when the lockfile already contained everything needed. Across these two releases, the lockfile is now updated in place — no registry round-trips, no churn beyond the entries that actually changed — for:

  • removing a dependency, including pruning what it alone made reachable and dropping a catalog entry that lost its last referent;
  • pnpm add of a version the lockfile already holds — promoting a transitive dependency to a direct one, or adding to a second workspace package what a first one already uses (#13696);
  • moving a dependency between dependencies, devDependencies, and optionalDependencies;
  • adding a new workspace package whose dependencies are all locked for a sibling;
  • widening or changing a range that an already-locked version satisfies — now picking the highest satisfying locked version, matching what a full resolution records (#13778);
  • changing a catalog entry to a different exact version, and combinations of catalog and pnpm.overrides edits with other changes (#13799);
  • changing pnpm.overrides to a satisfiable range, and parent-scoped overrides ("parent>child": "2.0.0") (#13795);
  • adding, editing, or removing patchedDependencies entries and ignoredOptionalDependencies patterns;
  • flipping autoInstallPeers, dedupePeers, peersSuffixMaxLength, excludeLinksFromLockfile, or injectWorkspacePackages when the lockfile proves the setting cannot affect the resolution.

Projects with a pnpmfile use these fast paths too, as long as the recorded pnpmfileChecksum proves the pnpmfile is unchanged. Every case that could change the resolution — a peer reached through the edited package, a dist tag, an exotic specifier — still falls back to a full resolution.

Git dependencies work on CI runners without SSH keys

Since v11.21.0, the Git resolver no longer records an SSH URL unless the specifier explicitly asks for one (git+ssh:// or git@host:...). A shorthand like github:owner/repo resolves and records over HTTPS, so a lockfile written on a machine with SSH keys no longer fails on a CI runner with Permission denied (publickey) (#13276). The repository visibility probe also retries throttled responses, and a repository that cannot be confirmed public keeps a regular git resolution so installs can use ambient credentials.

v11.22.0 improves what you see when Git resolution or fetching still fails: errors carry the ERR_PNPM_GIT_RESOLVE_FAILED / ERR_PNPM_GIT_FETCH_FAILED codes, name the dependency instead of printing a bare git invocation, redact credentials embedded in repository URLs, and explain how to route HTTPS URLs over SSH on machines that need it (#13743). An SSH URL recorded by a pre-11.21 lockfile can be re-recorded over HTTPS with pnpm update <package>.

Global installs switch over atomically

The command shims in the global bin directory now point at a stable per-package link rather than at the directory a particular install produced, so pnpm add -g and pnpm update -g activate a new version by moving one link instead of rewriting every shim. A command can no longer be missing from PATH while an install is in progress, and a failed install leaves the previous version in place.

The automatic packageManager switch works behind feed proxies

The automatic version switch works again on registries whose tarball URLs point at a different host than the registry itself (load-balanced feed proxies, Artifactory-style mirrors) (#13619), and registries that strip npm's signature metadata no longer break it or pnpm self-update: when the configured registry cannot provide a verifiable signature, pnpm fetches one from registry.npmjs.org and verifies it against the same embedded npm keys over the installed integrity (#13147).

Other notable fixes

  • resolutionMode: lowest-direct and time-based work again while minimumReleaseAge is in effect — including its built-in default, which previously forced the highest version silently (#13752).
  • pnpm update without saving no longer records a version the manifest's range excludes, which the next pnpm install --frozen-lockfile rejected (#12764).
  • pnpm deploy injects workspace dependencies again, so the deploy directory is self-contained instead of symlinking back into the source workspace (#13754).
  • pnpm add <pkg>@<version> under a non-manual catalogMode now moves the catalog entry's resolution instead of silently doing nothing, and catalogMode: strict accepts a version the catalog's range covers (#13715).
  • syncInjectedDepsAfterScripts survives FIFOs and file/directory swaps in workspace packages, removes bin links a build step stopped declaring, and identifies files by device as well as inode (#13550).
  • pnpm root -g and pnpm bin -g print warnings to stderr, keeping stdout a clean machine-readable path (#13672).
  • Lockfile verification honors offline mode, using cached registry metadata instead of reaching the registry.
  • pnpm audit --fix no longer adds minimumReleaseAgeExclude entries for patched versions old enough to pass the age gate anyway (#11563).
  • Shorthand Git dependencies, minimumReleaseAge dist-tag fallbacks, held-back-update warnings, link: dependencies under the global virtual store, and installs that only drop packages all received correctness fixes — the full lists are in the release notes.

For everything else in these releases, see the full notes for v11.21.0 and v11.22.0.