在打包过程中,分包(Code Splitting) 是一种优化技术,用于将代码拆分成多个较小的文件(chunks),以提高加载性能、优化缓存利用率并减少首屏加载时间。Webpack 和 Vite 分别采用不同的方式实现分包,以下是它们的核心实现方法及示例:
1. Webpack 的分包策略
Webpack 的分包主要通过 splitChunks 配置和动态导入(import())实现。
(1) 默认分包(splitChunks)
Webpack 默认会对 node_modules 中的第三方依赖进行分包,生成 vendor.js 文件。
配置示例:
// webpack.config.js
module.exports = {
optimization: {
splitChunks: {
chunks: 'all', // 对所有模块进行分包(包括同步和异步)
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/, // 匹配 node_modules 中的依赖
name: 'vendors', // 输出文件名
priority: 10, // 优先级
},
common: {
minChunks: 2, // 被至少 2 个模块引用的代码才会被分包
name: 'commons',
priority: 5,
},
},
},
},
};
效果:
-
node_modules中的依赖会被打包到vendors.js。 -
公共业务代码会被打包到
commons.js。
(2) 动态导入(路由懒加载)
使用 import() 动态加载模块,Webpack 会自动将其拆分成独立的 chunk。
示例(Vue Router):
const Home = () => import(/* webpackChunkName: "home" */ './views/Home.vue');
const About = () => import(/* webpackChunkName: "about" */ './views/About.vue');
效果:
Home.vue和About.vue会被拆分成home.js和about.js,按需加载5。
(3) 手动分包(DLLPlugin)
对于大型项目,可以使用 DLLPlugin 预打包第三方库,减少重复构建时间:
// webpack.dll.config.js
module.exports = {
entry: { vendor: ['react', 'lodash'] },
output: { filename: 'dll/[name].js', library: '[name]' },
plugins: [
new webpack.DllPlugin({
path: path.resolve(__dirname, 'dist/dll/vendor.manifest.json'),
name: '[name]',
}),
],
};
使用方式:
-
在
webpack.config.js中通过DllReferencePlugin引用预打包的库:new webpack.DllReferencePlugin({
manifest: require('./dist/dll/vendor.manifest.json'),
});
优点:
-
减少重复打包时间。
-
适合大型项目3。
2. Vite 的分包策略
Vite 基于 Rollup,其分包策略通过 build.rollupOptions.output.manualChunks 配置。
(1) 默认分包
Vite 默认会将 node_modules 中的依赖打包到 vendor.js,业务代码单独打包2。
(2) 手动分包
通过 manualChunks 可以自定义分包逻辑:
// vite.config.js
export default {
build: {
rollupOptions: {
output: {
manualChunks(id) {
if (id.includes('node_modules')) {
return 'vendor'; // 所有 node_modules 依赖打包到 vendor.js
}
if (id.includes('/utils/')) {
return 'utils'; // 工具函数单独分包
}
},
},
},
},
};
效果:
-
node_modules中的依赖 →vendor.js -
src/utils/下的代码 →utils.js
(3) 按包名分包
如果希望每个第三方库单独分包(如 react、lodash 独立):
manualChunks(id) {
if (id.includes('node_modules')) {
const pkg = id.split('node_modules/')[1].split('/')[0];
return `npm.${pkg}`; // 如 npm.react.js、npm.lodash.js
}
}
优点:
- 更细粒度的缓存优化6。
(4) 动态导入(懒加载)
Vite 支持动态导入,自动分包:
const loadModule = async () => {
const module = await import('./heavyModule.js'); // 自动拆分成独立 chunk
};
效果:
heavyModule.js会被拆分成独立文件,按需加载4。
3. Webpack vs. Vite 分包对比
| 特性 | Webpack | Vite |
|---|---|---|
| 分包方式 | splitChunks、DLLPlugin |
manualChunks |
| 动态导入 | import() + 魔法注释 |
import() |
| 缓存优化 | contenthash |
[hash] |
| 适用场景 | 大型复杂项目 | 中小型项目、快速构建 |
| 构建速度 | 较慢(需分析依赖) | 极快(ESM 原生支持) |
4. 最佳实践
(1) Webpack 优化建议
-
使用
splitChunks分离node_modules和公共代码。 -
对路由使用动态导入(懒加载)。
-
大型项目可结合
DLLPlugin预编译依赖3。
(2) Vite 优化建议
-
使用
manualChunks精细控制分包。 -
按包名拆分第三方库(如
react、lodash独立)。 -
结合动态导入优化首屏加载68。
总结
-
Webpack :通过
splitChunks和动态导入实现分包,适合复杂项目。 -
Vite :通过
manualChunks配置分包,依赖 Rollup,适合现代前端开发。
两种工具的分包核心目标都是减少首屏加载时间、优化缓存,具体选择取决于项目规模和构建需求。