在打包过程中,分包(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,适合现代前端开发。
两种工具的分包核心目标都是减少首屏加载时间、优化缓存,具体选择取决于项目规模和构建需求。