pnpm 11.11-11.14
pnpm 11.11 至 11.14 版本引入了原生的工作区发布管理功能(包括 pnpm change、pnpm lane 和纯粹的 pnpm version -r 命令)、用于端到端诊断安装状态的 pnpm doctor 命令、用于管理注册源上包与组织的 pnpm access 和 pnpm team 命令、收敛覆盖机制,以及支持协议标识符的 peerDependencies 声明。 它们还修复了一个路径遍历漏洞,将冷缓存解析期间的峰值内存占用降低了约 30%,并解决了对等依赖死锁问题。
次要更改
原生工作区发布管理
pnpm 现在可以独立对工作区进行版本管理和发布,无需借助单独的发布工具 (#12952)。 新的 pnpm change 命令用于记录变更意图——即兼容 changesets 格式的 .changeset/*.md 文件,其中包含了受影响的包、版本号变更类型以及将作为变更日志条目的摘要信息:
pnpm change
pnpm change status # 显示待发布的发布计划
在发布时,不带参数的 pnpm version -r 命令会处理这些变更:它会根据 workspace: 范围的依赖关系在整个工作区内提升版本号,生成变更日志,并将处理记录写入一个需提交的账本文件(.changeset/ledger.yaml)中,从而确保发布分支之间进行 cherry-pick 或 merge-back 操作时的安全性。
可以使用 pnpm lane 将包移动到针对单个包的发布通道上,从而在发布其他所有包的稳定版本的同时,发布 X.Y.Z-lane.N 格式的预发布版本:
pnpm lane alpha --filter @example/cli # 切换到 lane
pnpm lane main --filter @example/cli # 迁回稳定
相关配置位于 pnpm-workspace.yaml 中新增的 versioning 键下,包括 fixed、ignore、maxBump、lanes、epics 和 changelog。 发布变更日志默认使用 registry 存储方式:不提交 CHANGELOG.md 文件,每个版本的变更记录在发布时生成,并打包进发布的 tarball 中。 将 versioning.changelog.storage 设置为 repository,以便改为保留已提交的变更日志文件。
11.13 版本还新增了 versioning.epics 功能,该功能将一组从属包与一个主导包关联起来,并规定所有从属包的主版本号必须处于由主导包版本号派生出的特定范围内:当主导包处于主版本 M 时,从属包的版本号处于 M*100 到 M*100+99 这一区间 。 当发布计划引领进入一个新的稳定主版本时,所有成员都会基于同一计划中的基准分支进行变基操作。
请参阅版本发布管理了解完整的工作流程。
pnpm doctor
全新的 pnpm doctor 命令用于诊断 pnpm 的安装及其运行环境,具体检查内容包括:版本与安装方式、全局 bin 目录是否已加入 PATH、存储与缓存目录是否可写、存储所在文件系统支持的链接策略(reflink、hardlink、symlink)、存储库连接状况,以及一项涵盖解析、存储和链接全流程的离线 file: 安装测试。
✓ Versions: pnpm 11.14.0, Node.js 22.20.0
✓ Install method: pnpm
✓ Global bin directory: /Users/example/Library/pnpm/bin
✓ Cache directory: /Users/example/Library/Caches/pnpm
✓ Store directory: /Users/example/Library/pnpm/store/v10
✓ Filesystem: available: reflink, hardlink, symlink
✓ Registry connectivity: https://registry.npmjs.org/ (128ms)
✓ Install smoke test: offline "file:" install linked its dependency
All checks passed
每项检查都会报告如何修复其发现的问题,且若有任何检查失败,该命令将以非零状态码退出。 使用 --offline 跳过需要网络访问的检查,使用 --json 获取机器可读的输出,使用 --benchmark 测量文件系统和安装检查的耗时。
pnpm access 和 pnpm team
pnpm access 用于管理注册源上的包访问权限与可见性——包括列出包及协作者、获取与设置包的状态及 MFA 要求,以及授予或撤销团队访问权限:
pnpm access list packages @myorg
pnpm access set status=public @myorg/pkg
pnpm access grant read-write @myorg:developers @myorg/pkg
pnpm team 用于管理组织团队及成员资格,包含 create、destroy、add、rm 和 ls 子命令:
pnpm team create @myorg:developers
pnpm team add @myorg:developers alice
pnpm team ls @myorg
合并覆盖
一种新的带有空范围的覆盖选择器形式——"pkg@": "<version>"——仅在依赖项的具体版本满足该依赖项声明的范围时,才会重写其依赖边界;这意味着兼容的使用者会收敛到同一个版本,而不兼容的使用者则保留各自的解析结果,无论是在当前还是对于未来添加的任何依赖项 (#12794):
overrides:
"form-data@": 4.0.6
该数值必须是精确的版本。 当全解析检测到某个已声明的版本范围同时也包含更新的版本时,pnpm 会发出警告,提示该覆盖已过时,并指出应收敛到的目标版本。 此前,覆盖选择器中的空范围未在文档中说明,且其行为表现为普通的(无作用域的)覆盖。
peerDependencies 支持带有协议标识符的依赖声明
peerDependencies 现在接受带有协议的依赖标识符——例如命名注册表标识符(<registry>:<version>)、npm: 别名,或 file:/git/URL 标识符——而不再抛出 ERR_PNPM_INVALID_PEER_DEPENDENCY_SPECIFICATION 错误 (#13095)。 此类对等依赖会根据说明符中包含的语义范围进行匹配(例如 work:5.x.x 对应 5.x.x,npm:bar@^5 对应 ^5),若未指定版本则匹配 *;同时,原始说明符仍用于选择要自动安装的包。 裸 name@version 格式几乎总是错误,则仍会被拒绝。
pnpm run 支持正则表达式脚本选择器及 --sequential 选项
pnpm run 再次支持执行与正则表达式匹配的多个脚本(例如 pnpm run "/^build:.*/"),现在按确定的字典序运行匹配的脚本。 --sequential (-s) 选项也已恢复,它会将 workspaceConcurrency 强制设为 1,从而确保匹配的脚本在各个包之间及包内部逐个执行。
Portable delegation for custom fetchers
Custom fetchers exported from a pnpmfile can now delegate by returning a { delegate: <resolution> } envelope: pnpm rewrites the package's resolution to the delegated shape and runs the built-in fetcher on it. This is the portable delegation form that also works in pacquet, where cafs and fetchers cannot be passed to the hook.
Other minor changes
allowBuildsentries for git-hosted packages can now match by repository URL without pinning the resolved commit hash, so trusted git repositories keep running their build scripts after branch updates without approving each new commit. Package-name-only rules still do not approve git-hosted artifacts.registriesandnamedRegistriescan now be configured in the globalconfig.yamlfile.
Security
- Fixed a path traversal vulnerability where a dependency whose manifest
namewas a scoped path traversal (e.g.@x/../../../<path>) could be written outsidenode_modulesto an attacker-controlled location duringpnpm install, even with--ignore-scripts. - Prevented a crafted
pnpm-lock.yamlfrom writing package content outside the virtual store. Dependency path keys that reconstruct to a path-traversal sequence are now rejected by the isolated linker and the Plug'n'Play resolver map, and traversals in the version-derived path segment are rejected under the global virtual store. - Updated
adm-zipto prevent crafted ZIP archives from causing excessive memory allocation. ${...}environment-variable placeholders in thehttpProxy,httpsProxy,noProxy,proxy, andnoproxysettings are no longer expanded when these settings come from a project'spnpm-workspace.yaml.pnpm publishno longer prints credentials when the target registry is configured with inlineuser:pass@credentials.pnpm runtime set <name> <version>now validates its arguments, so an unsupported name or a comma can no longer be misread as a list of packages.- Broken-lockfile errors no longer include snippets of the lockfile's contents.
- Rejected symlinked
pnpm-lock.yamlfiles when reading or writing the env lockfile document. pnpm self-updatenow honorstrustPolicy=no-downgrade, and checks that the version it installed can run before making it the active pnpm.
补丁更改
- Reduced peak memory usage during cold-cache dependency resolution by roughly 30%, back in line with pnpm 10. The memoized metadata cache no longer retains each package's raw registry response body for the whole resolution phase.
- Fixed an out-of-memory regression when workspace projects concurrently resolve a package with large registry metadata (#13077).
- Fixed a deadlock in peer dependency resolution:
pnpm installhung forever when a peer dependency cycle spanned a project's own dependencies and auto-installed peer providers, for example when installingelectron-builder@26.15.3(#12921). - Fixed peer dependency auto-install picking a version the peer range rejects. Peers are now deduplicated onto the highest preferred version that satisfies the declared range, and when none does, the range is resolved from the registry.
- Fixed peer dependency resolution with
autoInstallPeerswhen a workspace package depends on a version of a package that a transitive dependency's self-contained closure also provides for itself (#4993). - Fixed
pnpm installfailing withERR_PNPM_LOCKFILE_IS_SYMLINKwhenpnpm-lock.yamlis a symlink, as build sandboxes such as Bazel and Nix stage it (#13073). An install that leaves the lockfile unchanged no longer rewrites it, so--frozen-lockfileno longer needs to write at all. - Fixed frozen installs incorrectly treating equivalent Git dependency specifiers as a stale lockfile (#13039).
- Fixed
pnpm updaterewriting exact version pins that use the=operator (for example=3.5.1) to a caret range. - Fixed
pnpm updateremoving transitive lockfile entries whendedupePeerDependentsis disabled and the selected package is absent (#12456). - Failed instead of silently removing an optional dependency's locked entries from
pnpm-lock.yamlwhen the registry cannot resolve it (#12853). - Retried package metadata requests when a registry or proxy returns
304 Not Modifiedto an unconditional request, and recovered from a metadata cache entry that disappears after a304(#12882). - Fixed the dependency status check wrongly reporting "up to date" when a
package.json,.pnpmfile.cjs, or patch file was edited in the same second as the previous install, on filesystems that record mtimes at whole-second resolution. pnpm deploynow supports workspaces that use catalogs, and localfile:tarball dependencies keep their package name in the generated deploy lockfile.pnpm packnow respects workspace-root.npmignoreand.gitignorefiles, and no longer applies workspace-root ignore rules when a workspace package has its own.npmignore.pnpm publishagain sends the package's README to the registry as metadata, and--otpis now sent correctly for bothpnpm publish --otpandpnpm publish --batch --otp.pnpm outdatedno longer checks the registry for dependencies resolved from locallink:,file:, orworkspace:references (#12827).pnpm listandpnpm whyno longer crash withEMFILE: too many open fileswhen a project has a large number of unsaved dependencies.pnpm cache deletenow removes a package's metadata from every metadata cache directory (#12753).- Fixed orphaned child processes on Windows when pnpm exits on an error while commands spawned by
pnpm execorpnpm dlxare still running (#12406). - Kept the interactive
minimumReleaseAgeapproval prompt visible duringpnpm install, so the install no longer hangs on a question the user cannot see (#13019). - A
tokenHelperset in the global pnpmauth.iniis no longer rejected as project-level configuration, and a helper that hangs is now killed after 60 seconds instead of leaving the command waiting forever. pnpm add -g,pnpm update -g,pnpm setup, and the self-updater no longer fail withERR_PNPM_MISSING_TIMEwhentrustPolicy: no-downgradeorresolutionMode: time-basedis set in the global config (#12883).- A project pinned to a broken pnpm release via
packageManagerordevEngines.packageManagernow reports which release is broken and what to do about it, instead of failing inside the installer. - The published
pnpmpackage no longer declaresdependenciesordevDependencies, sonpm installof the tarball no longer tries to resolve internal-only packages (#12955). - Fixed an injected workspace dependency incorrectly staying as
file:instead of deduping back tolink:(#10433). pnpm owner lsnow reports authentication and authorization failures as dedicated errors that include the registry's response body.- Options that follow
create,exec, ortestappearing as a subcommand of another command are now parsed instead of being silently treated as positional parameters. - The changed-packages filter (
--filter "...[<since>]") no longer allows an option-like<since>value to be interpreted as a git option, and the repository root is resolved to the nearest.gitentry so the filter works in a git worktree. verify-deps-before-runno longer spawns apnpm installwhen pnpm is executed in a directory that has nopackage.json.pnpm stage listnow stops paginating after a fail-safe cap of 1000 pages.- Registered the
pnalias in generated shell completion scripts, and fixed standalone installer downgrades from pnpm v12 to v11.
