前端打包优化相关 Webpack
打包时间的优化(基于 Vue CLI 4 + Webpack 5)
1. Webpack 配置减少打包时间
1.1 对 JS 配置:排除 node_modules
和 src
中的打包内容
在开发环境下,修改 Webpack 的 JS 规则,排除 /node_modules
和 src
目录中的 JavaScript 文件。这意味着 node_modules
和 src
目录中的 JavaScript 文件不会经过该规则定义的加载器处理(如 Babel 转译、ESLint 检查等)。
javascript
chainWebpack: (config) => {
// //编译时将项目的版本号作为一个全局常量ProjectVersion注入到代码中
config.plugin('define').tap((args) => {
args[0].ProjectVersion = JSON.stringify(ProjectVersion);
return args;
});
// 判断当前环境是否为开发环境
if (process.env.NODE_ENV === 'development') {
// 配置模块规则
config.module
.rule('js')
.exclude.add(resolve('/node_modules'))
.add(resolve('src'));
}
};
1.2 创建 DLL 配置文件,对第三方插件提前打包到本地
1.2.1 配置打包 DLL 文件
javascript
const path = require('path');
const webpack = require('webpack');
module.exports = {
mode: 'production', // 设置为生产模式
entry: {
// 将第三方库分组打包
vue: ['vue', 'vue-router', 'vuex'],
elementUI: ['element-ui'],
axios: ['axios'],
lodash: ['lodash'],
},
output: {
path: path.resolve(__dirname, 'dll'), // 输出目录
filename: '[name].dll.js', // 输出文件名
library: '[name]_library', // 全局变量名
},
plugins: [
// 生成 manifest 文件
new webpack.DllPlugin({
name: '[name]_library', // 需要与 output.library 一致
path: path.resolve(__dirname, 'dll/[name]-manifest.json'), // manifest 文件路径
}),
],
};
执行命令生成 DLL 文件:
bash
npx webpack --config webpack.dll.config.js
1.2.2 配置打包文件使用 DLL 文件并插入到模板中
javascript
configureWebpack: (config) => {
config.plugins.push(
// 引入分片的 DLL 文件
new webpack.DllReferencePlugin({
manifest: require(path.resolve(__dirname, 'public/dll/vue-manifest.json')),
}),
new webpack.DllReferencePlugin({
manifest: require(path.resolve(__dirname, 'public/dll/axios-manifest.json')),
}),
new webpack.DllReferencePlugin({
manifest: require(path.resolve(__dirname, 'public/dll/elementGui-manifest.json')),
}),
new webpack.DllReferencePlugin({
manifest: require(path.resolve(__dirname, 'public/dll/vueBaiduMap-manifest.json')),
}),
new webpack.DllReferencePlugin({
manifest: require(path.resolve(__dirname, 'public/dll/glodonTinymce-manifest.json')),
}),
new webpack.DllReferencePlugin({
manifest: require(path.resolve(__dirname, 'public/dll/elementChinaAreaData-manifest.json')),
}),
new webpack.DllReferencePlugin({
manifest: require(path.resolve(__dirname, 'public/dll/mintUi-manifest.json')),
}),
// 将分片的 DLL 文件添加到 HTML 模板中
new AddAssetHtmlPlugin([
{
filepath: path.resolve(__dirname, 'public/dll/vue.dll.js'),
publicPath: process.env.VUE_APP_PUBLIC_PATH, // 根据项目路径调整
},
{
filepath: path.resolve(__dirname, 'public/dll/axios.dll.js'),
publicPath: process.env.VUE_APP_PUBLIC_PATH,
},
{
filepath: path.resolve(__dirname, 'public/dll/vueBaiduMap.dll.js'),
publicPath: process.env.VUE_APP_PUBLIC_PATH,
},
{
filepath: path.resolve(__dirname, 'public/dll/elementGui.dll.js'),
publicPath: process.env.VUE_APP_PUBLIC_PATH,
},
{
filepath: path.resolve(__dirname, 'public/dll/glodonTinymce.dll.js'),
publicPath: process.env.VUE_APP_PUBLIC_PATH,
},
{
filepath: path.resolve(__dirname, 'public/dll/elementChinaAreaData.dll.js'),
publicPath: process.env.VUE_APP_PUBLIC_PATH,
},
{
filepath: path.resolve(__dirname, 'public/dll/mintUi.dll.js'),
publicPath: process.env.VUE_APP_PUBLIC_PATH,
},
])
);
},
1.3 开启多线程打包
使用 thread-loader
可能会达不到效果,因为开启多线程也需要时间。
javascript
// 开启多线程打包
config.module
.rule('vue')
.use('thread-loader')
.loader('thread-loader')
.tap(() => {
return {
workers: os.cpus().length,
};
})
.before('vue-loader');
1.4 删除无用的插件配置,去掉 sourceMap
javascript
chainWebpack: (config) => {
// 删除一些无用插件
config.plugins.delete('friendly-errors');
config.devtool = false; // eval|none source-map hidden-source-map // 不生成 sourceMap 源代码,减少体积,加快打包速度
};
1.5 删除 console.log
(生产环境),配置压缩 JS 和 CSS
javascript
// vue.config.js
const TerserPlugin = require('terser-webpack-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
module.exports = {
configureWebpack: {
optimization: {
minimize: true, // 启用压缩
minimizer: [
new TerserPlugin({
terserOptions: {
compress: {
drop_console: true, // 删除 console.log
pure_funcs: ['console.log'], // 只删除 console.log
},
format: {
comments: false, // 删除注释
},
},
extractComments: false, // 不提取注释到单独文件
}),
new CssMinimizerPlugin({
minimizerOptions: {
preset: [
'default',
{
discardComments: { removeAll: true }, // 删除所有注释
},
],
},
}),
],
},
},
};
2. 如何减少 Webpack 打包体积
2.1 按需加载
按需加载可以减少初始加载的代码量,提升页面加载速度。
2.2 Scope Hoisting
Scope Hoisting 会分析出模块之间的依赖关系,尽可能将打包出来的模块合并到一个函数中,减少函数声明和闭包的开销。
2.3 Tree Shaking
Tree Shaking 会去除没有引用的代码,减少打包体积。
通过以上优化措施,可以有效减少 Webpack 打包时间和体积,提升项目性能。