Webpack SplitChunks 实战经验与优化技巧分享
项目初期的技术选型
这个项目是一个中型的电商后台管理系统,功能模块比较多,代码量也挺大。一开始我用的是 Webpack 默认的打包配置,结果发现随着项目逐渐膨胀,打包后的文件体积变得特别大。首屏加载时间直接飙到了十几秒,用户根本没法用。
后来想了想,决定试试 Webpack 的 SplitChunks 插件。当时选这个技术的原因很简单:它能按需拆分代码,减少单个文件体积,提升加载速度。而且这玩意是 Webpack 内置的,不需要额外安装啥依赖,用起来也方便。
最大的坑:性能问题
刚上手 SplitChunks 时踩了不少坑,主要是对它的默认行为不太了解。比如,默认情况下,SplitChunks 只会提取公共模块到一个单独的 vendor 文件里。我当时以为这样就够了,结果发现有些第三方库(比如 lodash 和 moment)还是被打包进了业务代码,导致某些页面加载特别慢。
折腾了半天才发现,SplitChunks 的默认配置只对异步模块生效,而我们项目的大部分模块是同步加载的。这让我意识到,要想真正解决问题,必须手动调整配置。
核心代码就这几行
下面是我最终的配置代码,亲测有效:
module.exports = {
optimization: {
splitChunks: {
chunks: 'all', // 同步和异步模块都处理
minSize: 20000, // 模块最小体积,单位字节
maxSize: 50000, // 模块最大体积,超过会进一步拆分
minChunks: 1, // 模块被引用的最少次数
cacheGroups: {
vendors: {
test: /[\/]node_modules[\/]/, // 提取 node_modules 中的模块
priority: -10, // 优先级
name: 'vendors', // 输出文件名
},
common: {
minChunks: 2, // 至少被两个模块引用
priority: -20,
reuseExistingChunk: true, // 如果模块已经被打包过了,复用它
name: 'common', // 输出文件名
},
},
},
},
};
这里有几个点需要特别注意:
- chunks: ‘all’:这个参数很关键,它决定了是否处理同步模块。如果只写 async,那么同步模块不会被拆分。
- minSize 和 maxSize:这两个参数用来控制拆分粒度。开始我没设置 maxSize,结果有些第三方库被打包成了超大文件,加载还是很慢。
- cacheGroups:这是最核心的部分,通过 test 和 priority 来定义如何拆分模块。vendors 主要处理第三方库,common 处理业务代码中的公共部分。
踩坑提醒:这三点一定注意
在实际使用过程中,我遇到了几个常见的坑,分享给大家:
- 重复打包问题:刚开始我发现某些模块被重复打包了好几次,查了文档才知道是因为没设置 reuseExistingChunk。这个参数一定要加上,避免重复。
- 缓存失效问题:SplitChunks 拆分后,文件名可能会变,导致浏览器缓存失效。后来我在 output.filename 里加了 [contenthash],解决了这个问题。
- 动态导入兼容性:项目中有部分动态导入的模块,刚开始没处理好,导致运行时报错。后来发现需要确保动态模块的名字是稳定的,不能每次打包都变。
这些问题折腾了我好几天,尤其是缓存失效那块,一度怀疑是不是 SplitChunks 的锅。后来才反应过来是自己配置不当。
最终的效果评估
经过一番折腾,最终的效果还算不错:
- 打包后的 vendor 文件从原来的 2MB 减少到了 800KB 左右。
- 首屏加载时间从十几秒降到了 3 秒以内。
- 公共模块被成功提取出来,减少了重复加载的情况。
不过也有一些小问题没完全解决:
- 某些第三方库(比如 echarts)体积太大,虽然拆出来了,但加载速度还是有点慢。后续可能需要考虑按需加载。
- SplitChunks 的配置有点复杂,维护成本稍微高了一点。对于新人来说,理解起来可能会有点门槛。
总体来说,这个方案不是最优的,但胜在简单易用,适合像我们这种中型项目。
回顾与反思
总结一下,SplitChunks 确实是个好东西,但用得好不容易。刚开始我以为随便配一下就能搞定,结果踩了不少坑。最大的教训就是:不要盲目相信默认配置,一定要根据项目实际情况来调整。
以上是我个人对 Webpack SplitChunks 的完整讲解,有更优的实现方式欢迎评论区交流。这个技巧的拓展用法还有很多,后续会继续分享这类博客。

暂无评论