重复依赖问题
Rsdoctor 会在产物预警中报告对同一份产物中含有多个重复依赖包的情况
重复包的危害
- 安全性
- 很多包采用单例模式,默认用户使用时只会加载一次,如 core-js、react 和一些组件库会污染全局环境,多版本共存会引发运行时错误
- 运行时性能
- 增大产物体积,网络传输变慢
- 相同功能的代码运行多次
如何解决重复包问题?
解决依赖多版本的问题,可以从依赖和构建两个层面解决。
依赖层面
1. 使用 npm dedupe命令
一般包管理器会根据 semver 范围尽量安装相同版本的包,但由于 lock 文件的存在,长期项目可能会存在一些重复依赖。
包管理器会提供 dedupe 命令如 npm/yarn/pnpm dedupe 等,在 semver 正确的范围内进行重复依赖的优化。
2. 使用 resolutions
在 semver 的限制下,dedupe 命令的效果可能不是特别好。比如产物中包含的依赖为 [email protected] 和 [email protected] 它们分别被 "debug": "^4" 和另一个包的 "debug": "^3" 所依赖。
这时可以尝试使用包管理器的 resolutions 的功能,如 pnpm 的 pnpm.overrides、.pnpmfile.cjs 或 yarn 的 resolutions 等功能
。它们的特点是可以突破 semver 的束缚,安装时改变 package.json 中声明的版本号,来精确控制安装的版本。
但在使用前需要注意包版本之间的兼容性,评估是否有必要进行优化。例如:同一个包不同版本之间的逻辑变化是否会影响项目功能。
构建层面
使用 resolve.alias
几乎所有的打包工具都提供了自定义 npm 包解析路径的功能。因此我们可以通过在编译时手动指定 package 的 resolve 路径,来达到消除重复依赖的目的,例如:以 Rspack 或 Webpack 为例,如果 lodash 重复打包,我们可以进行如下配置,将所有 lodash 的 resolve 路径指定到当前目录的 node_modules 中。
这种方法同样需要注意包版本之间的兼容性。
常见的重复包处理案例
处理 pnpm-workspace 中的重复包
该项目中,web 依赖了 [email protected] 并通过 "component": "workspace:*" 引入了 component,component 依赖 [email protected]。项目结构如下:
在 apps/web 下执行 rspack build,打包 web 下的代码时,会解析到 [email protected],接着打包 component 下的代码时,会解析到 [email protected],这导致 web 项目的产物中同时含有两个版本的 React。
解决方案
此问题可以通过打包工具的 resolve.alias 来解决。让 Rspack 或 webpack 解析 React 时只解析到 apps/web/node_modules/react 这一个版本,示例代码如下:
Peer dependency 引起的重复包问题
这种处理方法同样适用于由于 pnpm workspace 中 peerDependencies 多分身引起的重复包的项目中,项目目录结构如下:
在该项目中,在 apps/web 下执行 rspack build,打包 web 下的代码时,会解析到 [email protected][email protected],接着打包 packages/component 下的代码时,会解析到 [email protected],它们虽然是同一版本,但路径不同,产物中也会存在两份 axios。
解决方案如下,让 web 项目构建时都只解析到 web 下 node_modules 的 axios 包即可。

