






















pnpm 11 来了! 此版本加强了 v10 周期中引入的安全默认设置,放弃了 npm CLI 发布回退,转而采用原生实现,将每个包的 JSON 存储索引替换为单个 SQLite 数据库,并将全局安装隔离,使其不再相互干扰。
它还需要 Node.js 22 或更高版本——pnpm 本身现在是纯 ESM。
从 v10 升级? 请参阅 从 v10 迁移到 v11 指南。 大多数配置更改都是机械性的,可以通过 pnpm-v10-to-v11 代码转换来应用。
minimumReleaseAge 默认为 1440(1 天),blockExoticSubdeps 默认为 true。allowBuilds 取代了旧版构建依赖项设置。 onlyBuiltDependencies、onlyBuiltDependenciesFile、neverBuiltDependencies、ignoredBuiltDependencies 和 ignoreDepScripts 已移除。pnpm add -g 都会获得自己的目录,其中包含自己的 package.json、node_modules 和 lockfile。pnpm publish、login、logout、view、deprecate、unpublish、dist-tag 和 version 不再委托给 npm CLI。.npmrc 仅用于身份验证/注册源。 其他设置必须放在 pnpm-workspace.yaml 或新的全局 config.yaml 中。 环境变量使用 pnpm_config_* 前缀。多项默认值已翻转为更安全的值:
| 设置 | 新的默认值 |
|---|---|
minimumReleaseAge | 1440(1天) |
minimumReleaseAgeStrict | false |
blockExoticSubdeps | true |
strictDepBuilds | true |
optimisticRepeatInstall | true |
verifyDepsBeforeRun | install |
新发布的软件包至少要过 1 天才能被解析。 若要选择退出,在 pnpm-workspace.yaml 中设置 minimumReleaseAge: 0。
allowBuilds 取代了旧的构建设置onlyBuiltDependencies、onlyBuiltDependenciesFile、neverBuiltDependencies、ignoredBuiltDependencies 和 ignoreDepScripts 都已被移除。 请改用 allowBuilds — 一个从包名称模式到布尔值的映射:
之前:
onlyBuiltDependencies:
- electron
onlyBuiltDependenciesFile: "allowed-builds.json"
neverBuiltDependencies:
- core-js
ignoredBuiltDependencies:
- esbuild
之后:
allowBuilds:
electron: true
core-js: false
esbuild: false
同时移除了:allowNonAppliedPatches(使用 allowUnusedPatches)和ignorePatchFailures(补丁失败现在会抛出异常)。
.npmrc 仅用于身份验证/注册源pnpm 不再从 .npmrc 读取非身份验证设置。 配置分为两类:
.npmrc, 全局rc文件, ~/.config/pnpm/auth.ini)。pnpm-workspace.yaml,新的全局 ~/.config/pnpm/config.yaml)。其他相关变更:
pnpm 不再读取 npm_config_* 环境变量。 请改用 pnpm_config_*(例如 pnpm_config_registry)。
pnpm 不再读取 package.json 中的 pnpm 字段。
pnpm 不再读取 npm 的全局配置,位于 $PREFIX/etc/npmrc。
网络设置(httpProxy、httpsProxy、noProxy、localAddress、strictSsl、gitShallowHosts)现在写入到 config.yaml / pnpm-workspace.yaml 中(仍然从 .npmrc 中读取以平滑迁移)。
pnpm-workspace.yaml 文件中新增的 registries 设置替换了 @scope:registry= 行:
registries:
default: https://registry.npmjs.org/
"@my-org": https://private.example.com/
"@internal": https://nexus.corp.com/
每个项目的 .npmrc 文件被 pnpm-workspace.yaml 文件中的 packageConfigs 文件取代:
packages:
- "packages/project-1"
- "packages/project-2"
packageConfigs:
"project-1":
saveExact: true
"project-2":
savePrefix: "~"
以前通过传递给 npm CLI 实现的命令要么已经以原生方式重新实现,要么已经移除。
重新实现:publish, view (info, show, v), login (adduser), logout, deprecate, unpublish, dist-tag, version, search, star/unstar/stars, whoami, ping, docs/home。
已移除(现在抛出“未实现”):access、bugs、edit、issues、owner、prefix、profile、pkg、repo、set-script、team、token、xmas。
关于新的原生 pnpm publish 的一些说明:
PNPM_CONFIG_OTP(以前是 NPM_CONFIG_OTP)。pnpm audit 使用批量建议端点注册源已停用旧版 /-/npm/v1/security/audits{,/quick} 端点。 pnpm audit 现在调用 /-/npm/v1/security/advisories/bulk,该命令不返回 CVE 标识符——因此,基于 CVE 的过滤已被基于 GHSA 的过滤所取代:
auditConfig.ignoreCves → auditConfig.ignoreGhsaspnpm audit --ignore <id> 和 --ignore-unfixable 读取和写入 GHSA要进行迁移,请将 ignoreCves 下的每个 CVE-YYYY-NNNNN 条目替换为匹配的 GHSA-xxxx-xxxx-xxxx(在 pnpm audit 的 More info 列中可见),并将其移动到 ignoreGhsas。
pnpm add -g <pkg> 和 pnx 现在使用全局虚拟存储,并且每个安装都会在 {pnpmHomeDir}/global/v11/{hash}/ 获得自己的独立目录,其中包含自己的 package.json、node_modules/ 和锁文件。 这样可以防止全局包之间因对等依赖冲突、提升更改或版本错位而相互干扰。
pnpm remove -g <pkg> 会删除包含该软件包的整个安装组。pnpm update -g [pkg] 会将软件包重新安装到一个新的隔离目录中。pnpm list -g 扫描隔离目录。pnpm install -g(不带参数)不再受支持——请使用 pnpm add -g <pkg>。全局安装的二进制文件现在位于 PNPM_HOME 的 bin 子目录中(而不是直接位于 PNPM_HOME 中),因此像 global/ 和 store/ 这样的内部目录不会污染 shell 自动补全。 升级后运行 pnpm setup 以更新 shell 配置。
pnpm link 也进行了收紧:只接受相对路径或绝对路径,移除了 --global(使用 pnpm add -g .),并且移除了不带参数的 pnpm link。
pnpm server.
useNodeVersion 和 executionEnv.nodeVersion — 使用 devEngines.runtime / engines.runtime。
hooks.fetchers — 已被 pnpmfile 中的新 fetchers 字段取代。
managePackageManagerVersions、packageManagerStrict 和 packageManagerStrictVersion。 这些都继承了旧版 packageManager 字段的 onFail 行为;新的 pmOnFail 设置包含了它们:
| 已移除 | 替换为 |
|---|---|
managePackageManagerVersions: true | pmOnFail: download(默认) |
managePackageManagerVersions: false | pmOnFail: ignore |
packageManagerStrict: false | pmOnFail: warn |
packageManagerStrictVersion: true | pmOnFail: error |
COREPACK_ENABLE_STRICT=0 | pmOnFail: warn |
| 命令 | 它的作用 |
|---|---|
pnpm ci | 运行 pnpm clean,然后运行 pnpm install --frozen-lockfile。 别名:clean-install、ic、install-clean. |
pnpm clean | 从所有工作区项目中移除 node_modules。 --lockfile 也会删除 pnpm-lock.yaml。 |
pnpm sbom | 生成 CycloneDX 1.7 或 SPDX 2.3 JSON 格式的软件物料清单。 |
pnpm peers check | 报告锁文件中未满足/缺失的对等依赖。 |
pnpm runtime set | 安装运行时;弃用 pnpm env use。 |
pnpm docs / home | 打开软件包主页。 |
pnpm ping | 向注册源发送 Ping 请求。 |
pnpm with | 在单次调用中以特定(或当前)版本运行 pnpm,绕过 packageManager 的版本限制。 |
pnpm pack-app | 通过 Node.js SEA 将 CommonJS 条目打包成一个或多个目标平台的独立可执行文件。 |
此外,还有上面“原生发布流程”下列出的原生重新实现的命令,以及 pnpm 的短别名 pn 和 pnpx/pnpm dlx 的短别名 pnx。
pnpm audit --fix=update通过更新锁文件 中的软件包来修复易受伤害性,而不是添加覆盖。 为了实现更精细的控制,新增的 --interactive / -i 标志允许你选择要修复的警示:
pnpm audit --fix=update --interactive
pnpm audit --fix 还会将每个安全公告的最小补丁版本添加到 pnpm-workspace.yaml 中的 minimumReleaseAgeExclude,这样就可以在不等待 minimumReleaseAge 的情况下安装安全修复程序。
现在可以使用 .mjs 扩展名以 ESM 格式编写 pnpmfiles。 当 .pnpmfile.mjs 存在时,它的优先级高于 .pnpmfile.cjs,并且只会加载其中一个。
该存储的重建围绕两个理念展开:减少读取,减少系统调用。
$STORE/index.db 的单个 SQLite 数据库(具有 MessagePack 值,WAL 模式用于并发访问),而不是位于 $STORE/index/ 下的数百万个 JSON 文件。 新索引中缺失的软件包会根据需要重新获取。package.json。<algo>-<digest>),并且哈希算法每个文件记录一次,而不是每个条目记录一次。 这样可以避免每次 CAS 路径查找时进行 base64 → hex 转换。许多小胜利增加了一个明显更快的安装:
undici 取代了 node-fetch 用于所有 HTTP 请求,具有 Happy Eyeballs(双栈)、更好的 keep-alive 和优化的全局调度器。If-Modified-Since 以进行条件获取。minimumReleaseAge 检查使用 简化的元数据 端点来获取更少的信息。node_modules 时,暂存目录消失了。gunzipSync 运行时使用更大的块大小,以减少 tarball 解压缩期间的缓冲区分配。通过 node@runtime:<version>(包括 pnpm env use 和 pnpm runtime set node)安装 Node.js 运行时不再从 Node.js 归档中提取捆绑的 npm、npx 和 corepack。 这大约减少了一半数量的pnpm需要哈希、写入CAS和链接的文件。 如果仍然需要 npm,请将其作为单独的软件包安装。
更清晰的脚本输出。 pnpm 现在打印 $ command(到 stderr,因此 stdout 保持管道友好),而不是 > pkg@version stage path\n> command。 只有在不同目录下运行时才会显示项目名称和路径。
安装过程中,对等依赖关系问题不再以树状结构呈现——pnpm 建议运行 pnpm peers check 来查看它们。
生命周期脚本不再从 pnpm 配置中获取 npm_config_* 环境变量;仅设置众所周知的 npm_* 环境变量,与 Yarn 一致。
当启用 init-package-manager 时,pnpm init 会写入 devEngines.packageManager 而不是 packageManager,并且默认的 type 现在是 "module"。
devEngines.packageManager 现在支持版本范围;解析后的版本存储在 pnpm-lock.yaml 中,如果仍然满足范围,则会被重用。
dedupePeers 是一个新设置,它使用仅包含版本信息的后缀 (name@version) 而不是完整的依赖路径,从而消除具有许多递归对等项的项目的嵌套后缀,例如 (foo@1.0.0(bar@2.0.0))。
pnpm approve-builds 现在接受用于非交互式使用的位置参数;在名称前加上 ! 即可拒绝。
隐藏脚本 — 以 . 开头的脚本只能从其他脚本调用,并且不会显示在 pnpm run 中。
-F 是 --filter 的新简短别名。
pnpm add 短标志 — -d 现在是 --save-dev,-p 是 --save-prod,-o 是 --save-optional,-e 是 --save-exact(仅在 pnpm add 内部)。
virtualStoreOnly 在不创建导入器符号链接、提升、bin 链接或运行生命周期脚本下填充虚拟存储。 在 Nix 构建中预先填充存储很有用。 pnpm fetch 现在内部使用此功能。
pnpm-workspace.yaml 中的 nodeDownloadMirrors 替换了 .npmrc 中的 node-mirror:<channel> 设置:
nodeDownloadMirrors:
release: https://my-mirror.example.com/download/release/
配置依赖项 现在已安装到 {storeDir}/links/ 中,并且符号链接到 node_modules/.pnpm-config/,因此它们可以在使用同一存储的项目之间共享。 已解析的版本和完整性哈希值已从 pnpm-workspace.yaml 移至 pnpm-lock.yaml 中的单独文档;旧的内联哈希项目会自动迁移。
有关代码转换和后续操作的完整指南,请参阅 从 v10 迁移到 v11。 简短版本:
.npmrc 移到 pnpm-workspace.yaml(或全局的 ~/.config/pnpm/config.yaml)。onlyBuiltDependencies 及其相关功能迁移到 allowBuilds。auditConfig.ignoreCves 迁移到 auditConfig.ignoreGhsas。pnpm setup 来更新你的 shell,以便将新的 bin 子目录添加到 PATH 中。完整的更改列表在 更改日志。 如果你依赖的某些功能缺失或损坏,请在 github.com/pnpm/pnpm/issues 上提交问题。
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。