面试题:项目中做过哪些 webpack 打包优化?分两类:构建速度优化、打包产物体积优化
🚀构建速度优化(打包变快)
- exclude排除node_modules,不要编译第三方库,节省大量时间
- babel-loader 开启cacheDiretory缓存
- thread-loader 多线程
- 配置resolve的extensions缩小查找范围,配置alias别名避免向上遍历,配置modules只找本项目的node_modules
- dev环境下不使用terser压缩
- dev环境下使用cheap-source-map
- 合理的devtools
- dev环境不使用minicssextraplugin 剥离css,不contenthash
📦产物体积优化(包变小),也就是减小首屏体积的优化
- 文件拆分(
分包+ 抽离css) 配合 contenthash内容hash 可以最大程度复用浏览器强缓存
- 懒加载异步分包: 最常见的就是路由懒加载
- 实现方式:webpack 遇到
import()动态导入语法,就会自动把这个模块打成单独的异步分包,不用手动去 splitChunks 里配 - 拆分目的:
减小首屏体积,只加载当前页面需要的代码,提升首屏速度
- 实现方式:webpack 遇到
- splitChunks(拆分js):公共模块抽离 同步分包
- 配置chunks:all; 可以同步异步代码都可以拆分提取公共的;
- 拆分目的:
去重代码,提取公共部分 + 后续访问命中缓存
- runtimeChunk:single webpack 运行时分包
- 拆分目的:
命中缓存
- 拆分目的:
- minicssextraplugin(把css 从js里抽出来): 抽离css
- 拆分目的:
命中缓存
- 拆分目的:
压缩:js 压缩 TerserPlugin;css 压缩 CssMinimizerPlugin资源压缩,小图片转base64,大的转文件, 或者提前压缩- 第三方库
按需引入,找体积合适的 - 生产环境
tree-shanking删除无用代码 基于ESM - 通过判断环境配置生产环境
excludes 大库,html里手动引入cdn
// webpack.config.js
const path = require('path')
const TerserPlugin = require('terser-webpack-plugin')
const isDev = process.env.NODE_ENV === 'development'
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[contenthash].js',
chunkFilename: '[name].[contenthash].chunk.js',
clean: true
},
module: {
rules: [
{
test: /\.js$/,
// ✅关键1:exclude排除node_modules,不要编译第三方库,节省大量时间
exclude: /node_modules/,
use: [
// ✅大项目开启多线程编译,小项目不要开(线程有创建开销)
{
loader: 'thread-loader',
options: { workers: 2 }
},
{
loader: 'babel-loader',
options: {
// ✅开启babel缓存,二次构建复用缓存,不用重复编译
cacheDirectory: true
}
}
]
},
{
test: /\.css$/,
use: isDev ? ['style-loader', 'css-loader'] : ['mini-css-extract-plugin.loader', 'css-loader']
}
]
},
resolve: {
// ✅减少后缀尝试的数量,加快模块查找
extensions: ['.js', '.vue'],
// ✅别名,减少向上递归查找文件
alias: {
'@': path.resolve(__dirname, './src')
}
},
// ✅开发环境用快的source‑map,不要完整源码映射
devtool: isDev ? 'cheap-module-eval-source-map' : 'source-map',
optimization: {
// 生产才压缩,开发关闭压缩,极大提升dev启动速度
minimizer: isDev ? [] : [new TerserPlugin()],
splitChunks: { chunks: 'all' },
runtimeChunk: 'single'
}
}