服务端阅读 05月28日 02:10
pnpm 的 overrides 和 resolutions 有什么区别?如何使用?
pnpm.overrides:原生覆盖机制pnpm.overrides 是 pnpm 原生的依赖覆盖配置,写在 package.json 的 pnpm 字段中,也可以写在 pnpm-workspace.yaml 里。// package.json{ "pnpm": { "overrides": { "lodash": "^4.17.21", "react": "^18.0.0" } }}# pnpm-workspace.yamloverrides: "lodash": "^4.17.21" "react": "^18.0.0"精确路径覆盖用 > 指定只覆盖某个包的依赖,不影响其他包对同一依赖的使用:{ "pnpm": { "overrides": { "webpack>lodash": "^4.17.21", "antd>rc-util": "^5.30.0" } }}也可以限定只覆盖特定版本的依赖:{ "pnpm": { "overrides": { "minimist@<1.2.6": "^1.2.6" } }}引用项目直接依赖用 $ 前缀引用项目自身声明的依赖版本,避免硬编码版本号导致不一致:{ "dependencies": { "react": "^18.2.0" }, "pnpm": { "overrides": { "react": "$react" } }}这样所有间接依赖的 react 都会使用项目声明的 ^18.2.0,而不是单独写一个版本。移除依赖用 - 可以把某个依赖从依赖树中移除:{ "pnpm": { "overrides": { "some-package>unused-dep": "-" } }}这在处理可选依赖或减少安装体积时有用。替换包将一个包替换为另一个:{ "pnpm": { "overrides": { "node-sass": "sass", "request": "axios" } }}对 peerDependencies 生效pnpm.overrides 会覆盖 peerDependencies 的版本解析。这在统一 React 版本时很常见——某些组件库的 peerDependency 声明了旧版 React,但你希望它们都使用项目中的版本。resolutions:Yarn 兼容字段resolutions 是 Yarn 的依赖覆盖字段,pnpm 为了方便从 Yarn 迁移的项目也支持读取它:{ "resolutions": { "lodash": "^4.17.21" }}resolutions 的局限resolutions 在 pnpm 中是兼容层,功能比 pnpm.overrides 少很多:不支持 > 路径指定,只能全局覆盖不支持 $ 引用直接依赖不支持 - 移除依赖不支持 @版本号 限定范围只能写在 package.json 中,不支持 pnpm-workspace.yaml两者优先级当 pnpm.overrides 和 resolutions 同时存在时,pnpm.overrides 优先级更高。如果同一条目两边都写了,以 pnpm.overrides 为准。有个已知问题:当 pnpm-workspace.yaml 中写了 overrides 时,package.json 里的 resolutions 可能被忽略而不是合并。所以迁移项目时建议把 resolutions 手动迁移到 pnpm.overrides,而不是两边混用。区别对比| 特性 | pnpm.overrides | resolutions ||------|----------------|-------------|| 路径指定(>) | 支持 | 不支持 || 版本限定(@版本) | 支持 | 不支持 || 引用直接依赖($) | 支持 | 不支持 || 移除依赖(-) | 支持 | 不支持 || 配置位置 | package.json 或 pnpm-workspace.yaml | 仅 package.json || peerDependencies 覆盖 | 支持 | 支持 || 优先级 | 高 | 低 || 来源 | pnpm 原生 | Yarn 兼容 |什么时候用哪个新项目直接用 pnpm.overrides,不需要考虑 resolutions。从 Yarn 迁移的项目,短期可以保留 resolutions 让项目先跑起来,但应尽快迁移到 pnpm.overrides,否则缺少路径指定和版本限定功能,覆盖精度不够,还可能遇到优先级冲突问题。常见使用场景修复传递依赖的安全漏洞第三方包依赖了有漏洞的旧版本,该包还没更新,你先手动覆盖:{ "pnpm": { "overrides": { "follow-redirects@<1.15.6": "1.15.6" } }}统一 React 版本monorepo 里不同包可能依赖不同版本的 React,用 $ 引用统一:{ "dependencies": { "react": "^18.2.0", "react-dom": "^18.2.0" }, "pnpm": { "overrides": { "react": "$react", "react-dom": "$react-dom" } }}只覆盖某个包的依赖某个包依赖了不兼容的版本,但你不想影响其他包:{ "pnpm": { "overrides": { "antd>rc-util": "^5.30.0" } }}验证覆盖效果修改 overrides 后需要重新安装依赖:pnpm install用以下命令确认覆盖是否生效:# 查看实际安装的版本pnpm list react# 查看某个依赖被谁引入pnpm why lodash# 查看完整依赖树pnpm list --depth=10注意事项全局覆盖要谨慎。把所有包的某个依赖强制升到大版本,可能导致不兼容。优先用路径覆盖(>)只影响目标包。修改 overrides 后记得重新 pnpm install,如果锁文件没更新,可以 pnpm install --force 强制刷新。