单个webpack打包产物存在重复依赖但package-lock.json无多版本记录

问题确认
你观察到的属于单打包产物下的依赖重复打包问题,哪怕package-lock.json中只有唯一版本记录也可能出现,不代表一定存在多版本依赖。
重复成因&结构差异说明
这种同版本重复打包、且结构不一致的情况,90%以上是同一个包被走了不同的模块入口导致的:
现在绝大多数第三方NPM包都会同时提供ESM(ES模块)和CJS(CommonJS)两种格式的产物,分别对应package.json中的module和main字段。如果你的业务代码、或者你依赖的其他第三方包,分别通过不同的规范引入了apollo、sentry,webpack会将两种格式的产物判定为不同的模块,分别打包进产物,自然结构会有明显差异。
除此之外还有两种少见的触发原因:
- webpack的resolve.modules配置优先级异常,导致同一个包从项目根目录node_modules、子依赖包下的node_modules两个路径被分别加载,哪怕版本完全一致也会被分开打包
- 配置的模块别名存在冲突,导致同一个包被匹配到了不同的解析路径
修复方案
- 首先排查模块引入路径:执行打包命令时添加
--json > stats.json参数导出打包统计文件,搜索apollo、sentry对应的模块路径,确认是否存在两个不同的入口文件(比如一个是xxx.cjs.js,一个是xxx.esm.js) - 固定依赖入口:如果是入口不一致导致的,在webpack配置的resolve.alias中为两个包指定统一的入口即可,示例配置如下:
const path = require('path') module.exports = { resolve: { alias: { '@apollo/client': path.resolve(__dirname, 'node_modules/@apollo/client/index.esm.js'), '@sentry/browser': path.resolve(__dirname, 'node_modules/@sentry/browser/index.esm.js') } } }
- 优化公共依赖提取规则:检查webpack的splitChunks配置,确保所有node_modules下的依赖都会被提取到公共chunk,避免重复打包:
module.exports = { optimization: { splitChunks: { chunks: 'all', cacheGroups: { vendors: { test: /[\\/]node_modules[\\/]/, name: 'vendors', priority: -10 } } } } }
- 调整模块解析优先级:在resolve.modules中配置优先读取根目录的node_modules,避免路径解析异常:
module.exports = { resolve: { modules: [path.resolve(__dirname, 'node_modules'), 'node_modules'] } }
内容的提问来源于stack exchange,提问作者Rob Allsopp
相关产品推荐
相关产品推荐

