webpack打包后bundle文件过大解决方案
文章类型:webpack
发布者:hp
发布时间:2026-07-14
通过webpack-bundle-analyzer搞清楚bundle里面装了什么,区分出业务代码还是其他三方占用。
npm install webpack-bundle-analyzer -Dconst { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
module.exports = {
// 其他基础配置
plugins: [
new BundleAnalyzerPlugin({
analyzerMode: 'server', // 启动本地服务自动打开分析页面
analyzerHost: '127.0.0.1',
analyzerPort: 8888, // 自定义端口,避免冲突
openAnalyzer: true, // 构建完成后自动打开浏览器
generateStatsFile: false, // 不生成额外的stats文件,避免冗余
})
]
};1:采用Tree Shaking剔除无用代码,只能识别 ES6 的 import/export 语法,CommonJS 的 require 完全不支持。同时注意css过滤,避免副作用影响。
// 全量引入整个 lodash 库,哪怕只用到一个方法
const _ = require('lodash');
const data = _.get(user, 'info', {});
//正确写法(支持 Tree Shaking):
// 只引入用到的单个方法,体积从70KB降到2KB
import get from 'lodash/get';
const data = get(user, 'info', {});
module.exports = {
mode: 'production', // 生产模式下自动开启部分优化
optimization: {
usedExports: true, // 标记未被使用的模块导出
sideEffects: false, // 标记无副作用的模块,允许安全删除未引用部分
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [
['@babel/preset-env', { modules: false }]
// 禁止 Babel 将 ES6 模块转成 CommonJS,否则 Tree Shaking 直接失效
]
}
}
}
]
}
};
{
"sideEffects": [
"*.css", "*.less", "*.scss"
]
}2:代码分割,利用SplitChunksPlugin把大bundle拆成小文件,设置体积大小,以及单独抽离三方依赖包
module.exports = {
optimization: {
splitChunks: {
chunks: 'all', // 同时对同步和异步模块生效
minSize: 20000, // 只有体积大于20KB的模块才会被拆分
minChunks: 1, // 至少被1个chunk引用就可以拆分
cacheGroups: {
// 单独抽离所有node_modules中的第三方依赖
vendors: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
priority: 10, // 优先级高于其他分组
reuseExistingChunk: true, // 复用已存在的chunk,避免重复打包
},
// 单独抽离体积较大的UI组件库
elementUI: {
name: 'element-plus',
test: /[\\/]node_modules[\\/]element-plus[\\/]/,
priority: 20,
},
// 抽离项目中自己写的公共工具函数
common: {
name: 'common',
minChunks: 2,
priority: 5,
}
}
}
}
}3:路由懒加载,实现按需加载,通过动态 import() 实现路由级别的代码分割,只有用户访问这个页面时才加载对应代码
// Vue 路由懒加载示例
const Home = () => import('@/views/Home.vue');
const About = () => import('@/views/About.vue');
const routes = [
{ path: '/', component: Home },
{ path: '/about', component: About }
];4:全量压缩,压缩js、css、各种代码注释,进一步缩小体积文件,部署时在 Nginx 中开启 Gzip 支持
npm install terser-webpack-plugin -Dconst TerserPlugin = require('terser-webpack-plugin');
module.exports = {
optimization: {
minimizer: [
new TerserPlugin({
parallel: true, // 开启多进程压缩,提升构建速度
terserOptions: {
compress: {
drop_console: true, // 删除所有console.log语句
drop_debugger: true, // 删除所有debugger语句
pure_funcs: ['console.log'] // 彻底移除console相关函数调用
},
format: {
comments: false, // 删除所有注释
}
},
extractComments: false, // 不单独生成LICENSE注释文件
})
]
}
};npm install css-minimizer-webpack-plugin -Dconst CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
module.exports = {
optimization: {
minimizer: [
new CssMinimizerPlugin({
minimizerOptions: {
preset: [
'default',
{ discardComments: { removeAll: true } } // 删除所有CSS注释
]
}
})
]
}
};
npm install compression-webpack-plugin -Dconst CompressionPlugin = require('compression-webpack-plugin');
module.exports = {
plugins: [
new CompressionPlugin({
algorithm: 'gzip',
test: /\.(js|css|html)$/,
threshold: 10240, // 只对大于10KB的文件进行压缩
minRatio: 0.8, // 压缩率小于0.8才生成压缩文件
})
]
};5:静态资源瘦身,针对图片和字体优化,小图片转Base64,或者采用cdn或者网络图片地址
image-webpack-loadermodule.exports = {
module: {
rules: [
{
test: /\.(png|jpe?g|gif|svg)$/i,
use: [
{ loader: 'url-loader', options: { limit: 8192 } }, // 小于8KB的图片转Base64内联
{
loader: 'image-webpack-loader',
options: {
mozjpeg: { quality: 80, progressive: true }, // JPG压缩
optipng: { enabled: false },
pngquant: { quality: [0.6, 0.8] }, // PNG压缩
gifsicle: { interlaced: false }, // GIF压缩
}
}
]
}
]
}
}6:第三包优化,替代重型库为轻量替代方案,超大库通过CDN外链引入,
npm install unplugin-auto-import unplugin-vue-components -D// webpack.config.js 配置externals
module.exports = {
externals: {
'echarts': 'echarts',
'vue': 'Vue',
'react': 'React'
}
};script src="https://cdn.jsdelivr.net/npm/vue@3/dist/vue.global.prod.js"></script>
<script src="https://cdn.jsdelivr.net/npm/echarts@5/dist/echarts.min.js">
暂无评论,快来发表第一条评论吧~