Webpack5打包体积过大,怎么优化才能减小vendor.js?
最近项目升级到Webpack5后,发现打包出来的 vendor.js 超过2MB,首屏加载特别慢。我已经用了 SplitChunksPlugin 做了基础拆分,但效果不明显。试过把 node_modules 单独拆出来,但有些第三方库还是被打包进 vendor 里,比如 lodash 和 moment。
下面是我目前的 splitChunks 配置:
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
vendor: {
test: /[\/]node_modules[\/]/,
name: 'vendors',
chunks: 'all',
}
}
}
}
是不是配置哪里不对?有没有更有效的拆包策略或者 Tree Shaking 没生效?
问题分析
先说为什么效果不明显:你现在的配置是把所有 node_modules 里的东西都塞进 vendors.js,lodash 和 moment 当然跑不掉。而且 moment 这种全量引入的库,Tree Shaking 本身就不太好使。
解决方案
第一步:把大库单独拆出来
把那些体积大的第三方库单独拆包,而不是混在 vendors 里:
这里需要注意 priority 参数,数值越高的会优先匹配,这样大库会被单独拆走。
第二步:解决 lodash 的 Tree Shaking
lodash 默认是全量导出的,Tree Shaking 很难生效。你有两个选择:
方案A:使用 lodash-es(推荐)
lodash-es 是 ESM 版本的,Tree Shaking 可以正常工作。
方案B:使用 babel-plugin-lodash
如果项目里lodash引用太多,改动太大,可以装这个插件自动按需导入:
第三步:moment.js 替换方案
moment.js 体积大是因为它把所有时区和 locale 数据都打包进去了。推荐换成 dayjs,只有 2KB 左右:
如果暂时不想换 moment,至少按需加载需要的 locale:
第四步:确认 Tree Shaking 真的生效
检查一下你的 package.json 和 webpack 配置:
然后在 package.json 里加上:
或者明确指定哪些文件有副作用:
总结一下
你目前配置的核心问题是把所有 node_modules 混在一起拆。按照上面的步骤来:
1. 先把 moment、lodash 这种大块头单独拆出来
2. lodash 换成 lodash-es 或者装 babel-plugin-lodash
3. moment 能换就换,不能换就只引入需要的 locale
4. 确保 production 模式 + usedExports + sideEffects 配置正确
这样一套下来,vendor.js 体积应该能降很多。如果还有问题,把你现在的 webpack 配置贴出来,我帮你看看具体哪里没配置好。
另外lodash用lodash-es替代,moment直接换dayjs,这两个体积差十几倍。