一、整体思路
Webpack 构建性能问题通常分为两类:
- 构建速度慢(
build time):包括初次构建、增量构建(开发模式 HMR)。 - 打包体积大(
bundle size):影响生产环境首屏加载速度。
优化方向:
- 减少 Webpack 处理的文件数量
- 缓存机制利用
- 分包和懒加载
- loader 和 plugin 优化
- 并行和多线程处理
- 构建分析和监控
二、模块解析优化(resolve & loader)
- 减少
resolve搜索范围
resolve: {
modules: ['src', 'node_modules'], // 避免默认路径递归查找
extensions: ['.js', '.ts', '.jsx', '.tsx'], // 按需添加,不要列太多
alias: { '@': path.resolve(__dirname, 'src') } // 缩短路径,避免相对路径递归查找
}
- Loader 优化
- 使用
include/exclude限制 loader 处理范围
{
test: /.ts$/,
use: 'ts-loader',
include: path.resolve(__dirname, 'src'),
exclude: /node_modules/
}
- 对
babel-loader或ts-loader使用缓存:
{
loader: 'babel-loader',
options: {
cacheDirectory: true, // 开启缓存,加快二次构建
}
}
- 减少 loader 链条
- 不要在每个文件都执行不必要的 loader,例如 style-loader -> postcss-loader -> sass-loader 过多处理。
三、构建缓存与增量编译
cache配置
cache: {
type: 'filesystem', // webpack 5 推荐
buildDependencies: {
config: [__filename] // 当配置文件变更时自动失效
}
}
- 硬盘缓存结合
babel-loader缓存
- 开发模式可以大幅度提升二次构建速度。
- 使用
thread-loader或esbuild-loader
- 对大型项目,可开启多线程处理 JS / TS 文件:
{
loader: 'thread-loader',
options: { workers: 4 }
}
- 或者用
esbuild-loader替换babel-loader,速度可以提升 5~10 倍。
四、分包策略
- 按需加载(路由级分包)
const Home = React.lazy(() => import('./pages/Home'));
splitChunks配置
- 提取公共库 / 第三方依赖:
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
vendors: {
test: /[\/]node_modules[\/]/,
name: 'vendors',
priority: -10,
},
common: {
minChunks: 2,
name: 'common',
priority: -20,
}
}
}
}
- 动态导入小模块
- 避免一次打包过多代码。
- CSS 分离
- 使用
mini-css-extract-plugin分离 CSS,避免 style-loader 热更新影响开发构建速度。
五、插件优化
- 限制不必要的插件
- 开发环境只保留 HMR、React Refresh。
- 生产环境才启用
MiniCssExtractPlugin、TerserPlugin、CompressionPlugin。
- 使用并行/缓存优化插件
TerserPlugin:
new TerserPlugin({
parallel: true, // 多线程压缩
terserOptions: { compress: { drop_console: true } }
})
CssMinimizerPlugin:
new CssMinimizerPlugin({ parallel: true })
- 删除不必要的 moment 本地化文件
new webpack.IgnorePlugin({ resourceRegExp: /^./locale$/, contextRegExp: /moment$/ });
六、资源与体积优化
- 图片/静态资源
- 使用
asset或url-loader小文件内联,大文件输出:
{
test: /.(png|jpg|gif|svg)$/,
type: 'asset',
parser: { dataUrlCondition: { maxSize: 8 * 1024 } } // 小于8kb内联
}
- Tree Shaking
-
确保:
- 使用 ES6 模块 (
import/export) sideEffects在package.json标记
- 使用 ES6 模块 (
{
"sideEffects": ["*.css"]
}
- 减少 polyfill
- 只按需引入:
import 'core-js/features/promise';
七、开发环境优化
- HMR 热更新
- React 使用
@pmmmwh/react-refresh-webpack-plugin - 减少 rebuild 范围,避免每次全量构建。
- SourceMap
- 开发模式用
cheap-module-source-map - 生产模式用
hidden-source-map或不生成(提升打包速度)
- 关闭性能提示
performance: { hints: false }
八、分析和监控
- Webpack Bundle Analyzer
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
plugins: [new BundleAnalyzerPlugin()]
- 分析包大小,找出冗余依赖。
- Speed Measure Plugin
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");
const smp = new SpeedMeasurePlugin();
module.exports = smp.wrap(webpackConfig);
- 找出耗时 loader 或 plugin。
- 静态分析依赖
- 用
webpack-bundle-size-analyzer或source-map-explorer找出大模块。
九、其他经验
- 外部化依赖(CDN)
- 对 React、ReactDOM 等大库,生产环境通过
externals引入 CDN。
- 避免重复依赖
- 多个子模块引入同一依赖,使用
dedupe或splitChunks提取。
- 合理使用 alias
- 避免深层路径造成模块解析慢。
- 控制 node_modules 文件处理
- 避免对整个 node_modules 执行 babel-loader。
- 升级 Webpack 版本
- Webpack 5 默认性能优化很多,开启 persistent caching。