依赖解析相关设置
overrides#
此字段允许你指示 pnpm 覆盖依赖关系图中的任何依赖项,包括对等依赖项。这对于强制所有软件包使用一个依赖项的单个版本、反向移植一个修复、用分叉替换依赖项或删除未使用的依赖项很有用。
请注意,overrides 字段只能在项目的根目录下设置。
overrides 字段的示例:
overrides:
"foo": "^1.0.0"
"quux": "npm:@myorg/quux@^1.0.0"
"bar@^2.1.0": "3.0.0"
"qar@1>zoo": "2"
你可以用 ">" 来覆盖某个包下的子依赖的版本,比如 qar@1>zoo 只会覆盖 qar@1 依赖的 zoo 的版本,而不会影响其他依赖。
若要保持被覆盖的版本与工作区其他位置使用的版本同步,请在 catalog 中定义该版本,并使用 catalog: 协议进行引用。这样一来,版本号便统一维护于一处,并同时被你的依赖项和覆盖项引用:
catalog:
foo: "^1.0.0"
overrides:
foo: "catalog:"
你也可以使用 catalog:<name> 引用已命名的目录。有关更多详细信息,请参阅 Catalogs。
如果你发现你使用某个包不需要它的依赖之一,你可以使用 - 来删除它。例如,如果软件包 foo@1.0.0 需要一个名为 bar 的大型软件包来实现你不使用的功能,删除它可以减少安装时间:
overrides:
"foo@1.0.0>bar": "-"
此功能对于 optionalDependencies 特别有用,其中大多数可选包可以被安全地跳过。
合并覆盖#
新增于:v11.13.0
带有空范围的选择器(即 "pkg@")是一种收敛覆盖(convergence override)。与无条件重写所有匹配边的常规覆盖不同,收敛覆盖仅在依赖边的版本满足该边所声明的版本范围时,才会重写该依赖边:
overrides:
"form-data@": 4.0.6
基于上述配置,声明 form-data: "^4.0.5" 的依赖会被锁定在 4.0.6 版本,而声明 ^3.0.0 的依赖则保持其原有的解析结果。这使得兼容的消费者能够统一使用同一个版本——无论是当前版本,还是未来添加的任何依赖版本——而无需强迫依赖图中的其他部分使用不兼容的版本。
规则:
- 该数值必须是精确的版本。使用版本范围、dist-tag 或
-移除操作时,会因ERR_PNPM_INVALID_CONVERGENCE_OVERRIDE错误而失败。只要catalog:引用能解析为确切版本,该引用就是允许的。 - 仅涉及普通的语义化版本依赖关系。对于声明为
workspace:、catalog:、npm:、dist-tag 或 git/URL 格式的依赖,由于不存在有意义的“满足”关系,它们将保持原样,不予处理。 - 收敛覆盖不能与父选择器组合使用:
"parent>pkg@"被拒绝。 - 常规覆盖总是优先于同一边缘的收敛覆盖。
当完整解析发现每个声明的范围都允许使用更高版本时,pnpm 会警告该覆盖已过期,并指明建议收敛到的版本。
注意
在 v11.13.0 版本之前,覆盖选择器中的空范围属于未公开文档的行为,且其表现与无范围限制(未指定范围)的覆盖相同。
覆盖对等依赖项#
覆盖规则也适用于 peerDependencies。该行为取决于覆盖中使用的版本说明符类型:
- 语义版本范围(例如,
^1.0.0)、工作区和目录协议:对等依赖项被覆盖,并且仍然是对等依赖项。 - 非范围指定符如“link:”或“file:”协议:对等依赖被覆盖并移至“依赖”,因为这些不是有效的对等依赖范围。
- 移除(
-):完全移除对等依赖项。
例如,要覆盖 react-dom 的 react 对等依赖项:
overrides:
"react-dom>react": "18.1.0"
packageExtensions#
packageExtension 字段提供了一种用额外信息扩展现有软件包定义的方法。例如,如果 react-redux 本应该在它的 peerDependencies 中包含 react-dom 但它没有,则可以用 packageExtensions 来填补上 react-redux。
packageExtensions:
react-redux:
peerDependencies:
react-dom: "*"
packageExtensions 中的键是包名或包名和 semver 范围,因此可以只修补包的某些版本:
packageExtensions:
react-redux@1:
peerDependencies:
react-dom: "*"
以下字段可以使用 packageExtensions 进行扩展: dependencies、optionalDependencies、peerDependencies 和 peerDependenciesMeta。
一个更大的例子:
packageExtensions:
express@1:
optionalDependencies:
typescript: "2"
fork-ts-checker-webpack-plugin:
dependencies:
"@babel/core": "1"
peerDependencies:
eslint: ">= 6"
peerDependenciesMeta:
eslint:
optional: true
提示
我们与 Yarn 一起维护一个 packageExtensions 的数据库,以便修补在生态系统中损坏的包。如果你使用 packageExtensions, 考虑发送一个 PR 上游并将你的扩展贡献给 [@yarnpkg/extension] 数据库。
allowedDeprecatedVersions#
此项设置允许忽略特定依赖包的 deprecation 警告。
示例:
allowedDeprecatedVersions:
express: "1"
request: "*"
使用上述配置,pnpm 将不会打印 request 任何版本和 express v1 版本的弃用警告。
update#
添加于:v11.16.0
本节中的设置用于调节pnpm update 和 pnpm outdated 命令。
update.ignoreDeps#
有时您无法更新依赖项。例如,最新版本的依赖项开始使用 ESM,但您的项目尚未采用 ESM。恼人的是,这样的包将始终被 pnpm outdated 命令打印出来,并在运行 pnpm update --latest 时更新。不过,你可以在“ignoreDeps”字段列出你不想升级的包:
update:
ignoreDeps:
- load-json-file
模式匹配也是支持的,因此你可以忽略在特定范围内的任何包: @babel/*。
update.changeset#
添加于:v11.16.0
- 默认值: false
- 类型:Boolean
当设为 true 时,pnpm update 在更新工作区清单后写入一条变更意图,为其 dependencies 或 optionalDependencies 被本次更新改动的每个工作区包声明 patch 提升,并在 peerDependencies 发生变化时声明 major 提升。等同于传入 --changeset;要针对单次运行覆盖该设置,请传入 --no-changeset。
update.githubActions#
添加于:v11.16.0
- 默认值: false
- 类型:Boolean
当设为 true 时,pnpm update 与 pnpm outdated 还会检查仓库工作流文件所引用的 GitHub Actions。等同于传入 --include-github-actions。参见更新 GitHub Actions。
update.githubActionsServer#
添加于:v11.17.0
- 默认值:
GITHUB_SERVER_URL环境变量,回退到 https://github.com - 类型:URL
工作流文件所引用的 GitHub Actions 所在 GitHub 服务器的基础 URL(例如 GitHub Enterprise Server)。该 URL 必须使用 https:// 或 http:// 协议。仅在可信网络中的可信服务器上使用 http://:用于把 action 固定到提交哈希的 ref 会通过该 URL 获取,而未加密的流量可能被篡改。
提示
在 v11.16.0 之前,update.ignoreDeps 名为 updateConfig.ignoreDependencies。已废弃的 updateConfig 设置在下一个主版本之前仍可工作;两者都设置时,update 部分优先,并会打印警告。
支持的架构#
你可以指定要安装的可选依赖项的架构,即使它们与运行安装的系统的架构不匹配。
例如,以下配置指示安装 Windows x64 的可选依赖项:
supportedArchitectures:
os:
- win32
cpu:
- x64
而此配置将为 Windows、macOS 以及当前正在运行安装的系统架构安装可选依赖项。它包括 x64 和 arm64 CPU 的工件:
supportedArchitectures:
os:
- win32
- darwin
- current
cpu:
- x64
- arm64
另外, supportedArchitectures 还支持指定系统的 libc。
ignoredOptionalDependencies#
如果可选依赖项的名称包含在此数组中,则会跳过它。例如:
ignoredOptionalDependencies:
- fsevents
- "@esbuild/*"
minimumReleaseAge#
添加于:v10.16.0
- 默认值:1440(自 v11 版本起),0(v11 版本之前)
- 类型:number (分钟)
为了降低安装受损软件包的风险,你可以延迟安装新发布的版本。大多数情况下,恶意发布会在一小时内被发现并从注册源中删除。
minimumReleaseAge 设置定义了版本发布后 pnpm 安装之前必须经过的最少分钟数。这适用于所有依赖项,包括传递依赖项。
例如,以下设置确保只能安装至少一天前发布的软件包:
minimumReleaseAge: 1440
minimumReleaseAgeExclude#
添加于:v10.16.0
- 默认值:undefined
- 类型:string[]
如果你设置了 minimumReleaseAge,但需要某些依赖项始终立即安装最新版本,则可以在 minimumReleaseAgeExclude 列出它们。排除由 软件包名称 起作用,适用于该软件包的所有版本。
示例:
minimumReleaseAge: 1440
minimumReleaseAgeExclude:
- webpack
- react
在这种情况下,所有依赖项必须至少存在一天,除了 webpack 和 react,它们在发布时立即安装。
添加于: v10.17.0
你也可以使用模式。例如,允许你组织中的所有包:
minimumReleaseAge: 1440
minimumReleaseAgeExclude:
- '@myorg/*'
添加于:v10.19.0
你也可以排除特定版本(或使用 || 的特定版本列表)。这允许固定对到期时间规则的例外:
minimumReleaseAge: 1440
minimumReleaseAgeExclude:
- nx@21.6.5
- webpack@4.47.0 || 5.102.1
minimumReleaseAgeExcludePrune#
添加于:v11.22.0
- 默认值: false
- 类型:Boolean
当设为 true 时,pnpm add、pnpm update 和 pnpm remove 会清理 pnpm-workspace.yaml 中 minimumReleaseAgeExclude 里新写入的锁文件不再解析的条目:已消失的版本会被移除(当某个条目的所有版本都不存在后即删除该条目),而锁文件中已不存在的包的条目同样会被移除。名称模式(@myorg/*)始终保持不变。
当本次安装的锁文件未覆盖整个工作区(sharedWorkspaceLockfile: false)时会跳过清理,因为其他项目仍需要的条目会被视为过期。
minimumReleaseAgeIgnoreMissingTime#
添加于:v11.0.0
- 默认值:true
- 类型:Boolean
当 true 时,pnpm 会跳过对注册源元数据中不包含 time 字段的软件包的 minimumReleaseAge 检查(一些私有注册源和镜像会省略它)。设置为 false 则在这种情况下解析失败,而不是安装软件包。
minimumReleaseAgeIgnoreMissingTime: false
minimumReleaseAgeStrict#
添加于:v11.0.0
- 默认值:如果
minimumReleaseAge被明确配置则true ,否则为 false - 类型:Boolean
控制当依赖项在请求的范围内没有满足 minimumReleaseAge 约束的版本时 pnpm 的行为。当为 false 时,pnpm 会回退到不满足 minimumReleaseAge 约束的版本,以便安装仍然可以成功。当为 true 时,pnpm 解析失败。
默认值取决于你是否自行配置了 minimumReleaseAge:如果你显式地设置了它(通过 pnpm-workspace.yaml、CLI 或环境变量),则默认情况下会启用严格模式,因此该设置会被强制执行。内置默认值 minimumReleaseAge(1440 分钟)并非严格限制,而是向后兼容。
minimumReleaseAgeStrict: true
trustPolicy#
添加于:v10.21.0
- 默认: off
- 类型:no-downgrade | off
当设置为 no-downgrade 时,如果软件包的信任级别与以前的版本相比有所下降,pnpm 将失败。例如,如果一个软件包之前是由受信任的发布者发布的,但现在只有来源信息而没有信任证明,则安装将会失败。这有助于防止安装可能已被入侵的版本。信任检查仅基于发布日期,而非语义版本控制。如果先前发布的版本具有更强的可信度证据,则无法安装该软件包。从 v10.24.0 开始,在评估非预发布版本安装的信任证据时,预发布版本将被忽略,因此受信任的预发布版本不能阻止缺少信任证据的稳定版本。
trustPolicyExclude#
添加于: v10.22.0
- 默认值:[]
- 类型:string[]
一份应排除在信任策略检查之外的包选择器列表。这样,即使特定的软件包或版本不满足 trustPolicy 要求,你也可以安装它们。
例如:
trustPolicy: no-downgrade
trustPolicyExclude:
- 'chokidar@4.0.3'
- 'webpack@4.47.0 || 5.102.1'
- '@babel/core@7.28.5'
trustPolicyIgnoreAfter#
添加于:v10.27.0
- 默认值:undefined
- 类型:number (分钟)
允许忽略发布时间超过指定分钟数的软件包的信任策略检查。这在启用严格的信任策略时非常有用,因为它允许安装旧版本的软件包(可能缺少带有签名或来源的发布流程),而无需手动排除,假设它们由于年代久远而安全。
trustLockfile#
添加于:v11.3.0
- 默认值: false
- 类型:Boolean
为 true 时,pnpm install 会跳过供应链验证步骤;该步骤通常会对已加载的 lockfile 中的每一项重新应用 minimumReleaseAge 和 trustPolicy 规则。安装过程将锁文件视为已受信任。
适用于锁文件实际上属于“可信基”一部分的环境——例如闭源项目,其中每一次提交都来自受信任的作者。“受污染”的锁文件(即贡献者在比 CI 强制执行的策略更宽松的条件下生成的锁文件)可能会漏检,因此,只要外部协作者能够编辑该锁文件,就应将此项设置为 false。
在大型工作区中,验证阶段会在安装期间将各包的注册源元数据保留在内存中;禁用该阶段可降低内存占用,但会牺牲供应链检查功能。对于大多数采用默认 frozenLockfile CI 工作流的项目,无需设置此项。
blockExoticSubdeps#
添加于:v10.26.0
- 默认值:true
- 类型:Boolean
设置为“true”时,只有直接依赖项(在根目录 package.json 中列出的依赖项)才能使用特殊来源(例如 git 仓库或直接 tarball URL)。所有传递依赖项都必须从受信任的来源解析,例如配置的注册表、本地文件路径、工作区链接或受信任的 GitHub 存储库(node、bun、deno)。
此设置有助于保护依赖项供应链,防止传递依赖项从不受信任的位置引入代码。
异域资源包括:
- Git 仓库(
git+ssh://...) - 直接链接到 tar 包(
https://.../package.tgz)
registries#
添加于:v11.0.0
- 默认值:undefined
- 类型:Record<string, RegistryDeclaration> 或 Record<string, string>
声明项目从中安装的注册源。自 v11.23.0 起,每个注册源都以其 URL 为键声明一次,条目中记录了 pnpm 对该注册源的所知:路由到它的 scopes、它响应的裸说明符 prefix,以及服务器组织 tarball URL 的方式(serverType、supportsTimeField)。每个字段的完整说明见专门的注册源页面。
registries:
https://npm.corp.example.com/:
serverType: artifactory
scopes: ["@my-org", "@internal"]
prefix: work
把作用域映射到 URL 的旧结构仍然被接受。 default 键用于设置主注册源(等同于 .npmrc 的 registry 设置),带作用域的键则为特定包作用域配置注册源:
registries:
default: https://registry.npmjs.org/
"@my-org": https://private.example.com/
"@internal": https://nexus.corp.com/
同一个映射中不能混用两种结构。
自 v11.11.0 起,该设置还可以定义在全局配置文件(config.yaml)中,这对需要作用于机器上所有项目(而非单个仓库)的注册源很有用。从那里只会读取路由(scopes 和 prefix);serverType 与 supportsTimeField 会影响锁文件,因此仅从 pnpm-workspace.yaml 读取 — 参见该设置可以放在哪里。
namedRegistries#
添加于:v11.1.0
- 默认值:undefined
- 类型:** Record <string, string>**
注意
自 v11.23.0 起已废弃:请改为在 registries 中声明 prefix — 参见注册源页面。 namedRegistries 仍会被读取,但仅针对 registries 未声明的前缀;若两者都声明了前缀,pnpm 会给出警告。下文关于别名的一切 — 内置别名、保留名称与锁文件键 — 同样适用于由 prefix 声明的别名。
定义命名的注册源别名,在安装包时可以用作前缀,以 vlt 的命名注册源别名的风格。例如,使用以下配置:
namedRegistries:
gh: https://npm.pkg.github.example.com/
work: https://npm.work.example.com/
pnpm add work:@corp/lib@^2.0.0 将 @corp/lib@^2.0.0 解析为 https://npm.work.example.com/。
身份验证信息来自现有的每个 URL 的 .npmrc 条目(例如 //npm.pkg.github.com/:_authToken=...),因此不需要单独的身份验证机制。
自 v11.11.0 起,该设置也可以定义在全局配置文件(config.yaml)中,这样像 work: 这样的别名就能在机器上的所有项目间共享。
内建别名#
无需任何配置即可使用两个别名:
| 别名 | 注册源 | 备注 |
|---|---|---|
gh: |
https://npm.pkg.github.com/ |
GitHub Packages 的 npm 注册源。 |
npmjs: |
https://registry.npmjs.org/ |
公共的 npm 注册源。添加于 v11.20.0。 |
在 namedRegistries 下定义的条目会合并到这些别名之上,因此两者都可被覆盖 — GitHub Enterprise Server 用户会把 gh 指向自己的主机,而做 npmjs 镜像或代理的组织应把 npmjs 指向该镜像:
namedRegistries:
gh: https://npm.pkg.github.example.com/
npmjs: https://npm.internal.example.com/
即使默认的 registry 指向别处,例如内部代理,npmjs: 也会把依赖固定到公共注册源:
{
"dependencies": {
"left-pad": "npmjs:^1.3.0"
}
}
npm: 前缀做不到这一点 — 它是别名协议(npm:<name>@<range>),会通过 registry 指向的位置来解析。
当 pnpm 校验包时,内置 URL 同时也是用于匹配锁文件中记录的 tarball URL 的前缀。如果你代理 npmjs 却没有覆盖该别名,那么 tarball URL 位于 registry.npmjs.org 的条目会针对公共注册源校验,而不是你的镜像。这只影响会记录此类 URL 的锁文件 — 你已配置注册源的规范 URL 会从锁文件中被省略 — 且仅在执行 tarball URL、minimumReleaseAge 或 trustPolicy 检查时发生。
保留的别名名称#
自 v11.20.0 起,若别名遮蔽了保留的依赖说明符前缀(file、link、workspace、runtime、npm、jsr、git、github、gitlab、bitbucket、catalog、custom、http、https、ssh),就会以 ERR_PNPM_RESERVED_NAMED_REGISTRY_NAME 被拒绝。以前,此类别名会被对应的解析器静默遮蔽。别名还必须以字母开头,且只能包含字母、数字、.、_ 和 -。
锁文件中的命名注册源#
自 v11.20.0 起,从命名注册源解析的包会以带注册源限定的键记录在 pnpm-lock.yaml 中,形如 <name>@<registryName>:<version>:
packages:
foo@work:1.0.0:
resolution: {integrity: sha512-...}
在 v11.20.0 之前,包只以 name@version 为键,因此两个注册源提供的同名同版本会合并为同一个条目,而先解析到的那个决定了所有使用者拿到的 tarball。这就带来了包替换风险:你期望来自私有注册源的包,可能由另一个发布了同名同版本的注册源安装,而锁文件对此毫无提示。带注册源限定的键让每个注册源拥有各自的条目,并固定依赖来自哪个注册源。
锁文件格式版本未变,限定键仅出现在从命名注册源解析的包上 — 包括无需 namedRegistries 条目的内置 gh: 和 npmjs: 别名。没有通过别名安装任何内容的项目看不出差别,旧版 pnpm 也能继续读取该文件。
注意
若有依赖通过别名安装,你在 v11.20.0 或更新版本上的首次非冻结安装会重新为这些条目生成键,并表现为锁文件差异。把它提交 — 那份差异正是修复生效的体现。也要审查它:若某个条目迁移到了你未曾预期的注册源,值得调查。
请先让所有参与该项目的人升级到 v11.20.0 或更新版本。旧版 pnpm 能正常读取重写键后的锁文件,冻结安装亦不受影响,但它自身不会生成带注册源限定的键:任何更新锁文件的安装都会把这些条目写回旧结构,而随后在当前版本 pnpm 上安装又会重新加上限定。于是锁文件反复翻转,只要它还处于旧结构,项目便再次面临暴露。由于锁文件格式版本被有意保持不变,pnpm 无法检测这种情况,也无法提醒你。
不存在保留旧行为的设置 — 旧结构本身就是漏洞。
锁文件引用的所有非内置别名都必须保持已声明 — 通过 registries 中的 prefix,或通过 namedRegistries。若所读条目的别名已不存在,会以 ERR_PNPM_MISSING_NAMED_REGISTRY 失败,而不会回退到默认注册源,因为那会取到别的包。重命名别名会导致使用该别名的包被重新解析。
对命名注册源包而言,符合标准注册源布局的 tarball URL 不再写入锁文件;它们会在需要时根据别名声明的 URL 重新计算。