当你打开一个网站,结果首页白屏好几秒,开发者工具一看:
一个 5MB 的 bundle.js 正在慢吞吞下载。
这时候,你可能会想:
“前端同学是不是把整个世界都打包进来了?”
别急,其实 Webpack 给我们准备了一把“解剖刀”—— splitChunks,它能把臃肿的 bundle.js 切成小块,让用户更快加载页面。
一、为什么需要 splitChunks?
如果你写过 React/Vue 项目,可能遇到这种情况:
- 引入了
lodash,结果只用到一个函数; - 用了 UI 库(antd、element),结果只需要几个组件;
- 多个页面用到了相同的库,但却在每个 bundle 里重复打包。
这些问题的最终表现就是:
👉 bundle 体积爆炸,加载速度直线下降。
splitChunks 就像一个聪明的打包师傅:
- 看看哪些代码可以“公用”;
- 把大的依赖拆出去做“vendor”;
- 给用户按需送上“套餐”,而不是强塞一个大锅饭。
二、splitChunks 是怎么切的?
在 Webpack 4+ 中,splitChunks 内置在 optimization.splitChunks 配置里。一个最经典的配置如下:
// webpack.config.js
module.exports = {
optimization: {
splitChunks: {
chunks: 'all', // 对同步(initial)+异步(async)代码都生效
minSize: 20000, // 模块超过 20KB 才会被提取
minChunks: 1, // 模块至少被引用 1 次才会提取
cacheGroups: {
vendors: { // 针对第三方库
test: /[\/]node_modules[\/]/, // 匹配 node_modules 下的模块
name: 'vendors', // 生成文件名
priority: -10 // 优先级,高于 default
},
default: { // 针对自定义模块
minChunks: 2, // 至少被两个不同模块引用才会提取
priority: -20, // 优先级低于 vendors
reuseExistingChunk: true // 如果已有 chunk 满足条件,就复用
}
}
}
}
}
参数详解
| 参数 | 含义 | 小贴士 |
|---|---|---|
chunks | 'all'、'async'、'initial' | 'all' 最常用,能覆盖同步+异步模块。 |
minSize | 提取的最小字节数 | 太小的模块不单独生成 chunk,避免文件太碎。 |
minChunks | 模块被引用次数 | default cacheGroup 很关键,保证重复使用的模块才提取。 |
cacheGroups | 缓存组配置 | 可自定义 vendor/common/chunk 的策略。 |
priority | 优先级 | 如果模块同时符合多个 cacheGroup,优先级高的会先抽离。 |
reuseExistingChunk | 是否复用已有 chunk | 避免重复生成相同模块 chunk,提高缓存利用率。 |
vendors 与 default
-
vendors
- 针对第三方库(如
react、lodash、antd) - 优先级高于 default
- 生成的文件通常命名为
vendors.js或vendors.[contenthash].js
- 针对第三方库(如
-
default
- 针对项目内部模块
minChunks: 2保证至少被两个页面或模块引用reuseExistingChunk: true避免重复生成相同模块 chunk,提高缓存效率
🔹 总结:vendors 优先抽离第三方库,default 用于复用内部重复代码。
三、用个例子说明
假设我们有两个页面:pageA 和 pageB。
// pageA.js
import _ from 'lodash';
import { Button } from 'antd';
// pageB.js
import _ from 'lodash';
import { Table } from 'antd';
如果不做优化,最后可能会打出两个大文件:
pageA.bundle.js(包含 lodash + antd + 业务代码)pageB.bundle.js(又包含 lodash + antd + 业务代码)
开启 splitChunks 后:
- lodash 和 antd 会被抽到
vendors.js pageA.bundle.js和pageB.bundle.js只包含各自的业务逻辑- 浏览器会并行加载
vendors.js+ 页面文件,提升速度 🚀
注意:如果 lodash、antd 被多个页面引用,开启 splitChunks 后只打包一次,浏览器缓存一次就好,其他页面复用,不再重复下载。
四、真实项目中的实践技巧
-
按需切割 UI 库
- 使用
babel-plugin-import或unplugin-vue-components,避免整库打包 - splitChunks 再来一刀,效果更佳
- 使用
-
合理设置缓存组 (cacheGroups)
- 常用工具库(lodash、dayjs)可以单独抽成
common.js,避免混在 vendors 里
- 常用工具库(lodash、dayjs)可以单独抽成
-
利用浏览器缓存
- vendors 和 common 模块通常不常改动,可以长期缓存
- 业务代码变动时,用户只需要更新小文件,加载更快
-
chunk 命名策略
- 生产环境建议使用
[name].[contenthash].js命名,配合缓存策略
- 生产环境建议使用
五、形象比喻:自助餐 vs 大锅饭
- 没用 splitChunks:所有菜(代码)都放到一口大锅里,顾客(用户)只能端走一大碗
- 用了 splitChunks:自助餐,用户只拿自己需要的盘子(页面代码),公共的调料区(vendors)大家共用
这样既省钱(带宽),又高效(加载速度快)。
六、总结
splitChunks 的核心价值就是:
👉 让代码更合理地切割和复用,避免重复打包,提升加载速度
- Tree-Shaking = “减肥” → 去掉没用的代码
- splitChunks = “分餐制” → 把代码合理分配
两者配合,让前端项目既精简又高效。
你在项目里用过 splitChunks 吗?踩过哪些坑?欢迎在评论区分享!