如何提升 Webpack 的二次构建速度(
提升 Webpack 的二次构建速度(即热更新 HMR 或重新编译的速度),核心思路是“充分利用缓存”和“减少不必要的重复计算/文件解析”。
以下是经过生产环境验证的最有效的优化策略,按推荐程度从高到低排列:
1. 开启 Webpack 5 原生持久化缓存(最有效)
Webpack 5 引入了强大的文件系统缓存(FileSystem Cache),能将构建过程中的模块和 Chunk 缓存到磁盘中,这是提升二次构建速度最明显的手段(通常能提升 70%~90%)。
在 webpack.config.js 中配置:
module.exports = {
// ...
cache: {
type: 'filesystem', // 使用文件系统缓存
buildDependencies: {
// 当配置文件发生变化时,缓存失效
config: [__filename],
},
// 可选:指定缓存目录,默认在 node_modules/.cache/webpack
name: 'development-cache',
},
};
注:如果是 Webpack 4,需要使用
cache-loader或hard-source-webpack-plugin(但建议直接升级到 Webpack 5)。
2. 替代传统 Transpiler(用 ESBuild / SWC 替换 Babel)
Babel 解析和转换 JS/TS 的速度较慢。使用 Rust/Go 编写的编译器替代 Babel,可以极大加快二次编译的速度。
- 使用
esbuild-loader:javascriptmodule.exports = { module: { rules: [ { test: /\.[jt]sx?$/, loader: 'esbuild-loader', options: { loader: 'tsx', // target: 'js', 'jsx', 'ts', 'tsx' target: 'es2015', }, }, ], }, }; - 或者使用
swc-loader(Next.js 同款)。
3. 如果继续使用 Babel,开启 Babel 缓存
如果无法替换 Babel,务必确保开启了 babel-loader 的缓存:
module.exports = {
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
cacheDirectory: true, // 开启 babel 编译缓存
cacheCompression: false, // 关闭压缩以节省 CPU 时间(开发环境)
},
},
},
],
},
};
4. 优化 Source Map 格式
Source Map 的生成方式对二次构建性能影响巨大。在开发环境中,应选择构建速度快且支持增量映射的格式。
- 推荐开发环境配置:javascript
module.exports = { // 最佳折中方案:编译速度极快,定位到行,包含 Loader 映射 devtool: 'eval-cheap-module-source-map', }; - 避免在开发环境使用:
source-map、inline-source-map等全局重新计算的格式。
5. 精确缩小文件的检索与处理范围
不让 Webpack 去做无用功,减少递归查找的时间。
(1) 精确匹配 Loader 作用范围
确保使用 include 限制范围,或使用 exclude 排除 node_modules:
{
test: /\.js$/,
include: path.resolve(__dirname, 'src'), // 只处理 src 下的文件
use: ['babel-loader']
}
(2) 缩小模块决议(Resolve)范围
module.exports = {
resolve: {
// 1. 尽量减少后缀尝试(Webpack 从左到右匹配)
extensions: ['.tsx', '.ts', '.js'],
// 2. 绝对路径指定 node_modules,避免递归向上查找
modules: [path.resolve(__dirname, 'node_modules'), 'node_modules'],
// 3. 使用 alias 减少路径计算
alias: {
'@': path.resolve(__dirname, 'src'),
},
},
};
(3) 忽略大型无依赖库(module.noParse)
对于没有 import/require 依赖项的大型第三方库(如 lodash、chart.js、jquery),跳过 AST 语法树解析:
module.exports = {
module: {
noParse: /jquery|lodash/,
},
};
6. 使用 thread-loader 进行多进程构建
如果项目非常庞大,单进程处理耗时较长,可以将耗时的 Loader(如 babel-loader)放入 Worker 线程池中并行处理。
module.exports = {
module: {
rules: [
{
test: /\.js$/,
include: path.resolve('src'),
use: [
{
loader: 'thread-loader',
options: {
workers: 2, // 产生的 worker 线程数
},
},
'babel-loader',
],
},
],
},
};
注意:每个 Worker 启动都有约 600ms 开销。小型项目使用
thread-loader反而会导致速度变慢,请根据项目体量谨慎使用。
7. 开发环境关闭不必要的产物优化
在开发环境中,应当尽可能关闭压缩、Hash 生成以及不必要的插件:
- 关闭代码压缩:设置
mode: 'development'默认会关闭压缩(不要手动加TerserPlugin)。 - 文件名不要加 Hash:开发环境输出写死文件名即可(如
[name].js),避免每次重建重新计算 Hash。 - 避免在开发环境使用
MiniCssExtractPlugin:提取 CSS 很耗时,开发环境直接使用style-loader内联在 JS 中,热更新更快。
快速检查与诊断工具
如果做完上述配置后二次构建依然很慢,可以使用以下工具进行诊断:
speed-measure-webpack-plugin:测量每个 Loader 和 Plugin 的消耗时间,精准定位“耗时大户”。UnusedWebpackPlugin:清理项目中未引用的残留文件。
总结推荐配置组合(开发环境)
- 升级到 Webpack 5。
- 开启
cache: { type: 'filesystem' }。 devtool: 'eval-cheap-module-source-map'。- 用
esbuild-loader替代babel-loader(或开启cacheDirectory)。 - 正确设置 Loader 的
include和resolve.extensions。
如果项目规模巨大,即便经过 Webpack 深度优化仍无法满足需求,可以考虑迁移到底层基于 Rust 的 Rspack(无缝兼容 Webpack 生态且速度极快)或使用 Vite。