| 维度 | v1 原版 | v2 更新版 |
|---|---|---|
| Webpack 版本 | 5.36.x | 5.107 |
| 官方内置工具 | 简要提及 --json | 深度解析 stats/ProgressPlugin/webpack-dashboard |
| Bundle Analyzer | 基础用法 | 三种模式(static/server/JSON)+ 最新 API |
| Speed Measure Plugin | 基础用法 | 增加 Webpack 5 兼容性警告 |
| 新增工具 | 无 | webpack-stats-plugin / bundle-stats |
| 缓存分析 | 未涉及 | cache.profile / cacheUnaffected 实验特性 |
| 方法论 | 工具罗列 | 识别瓶颈→定位原因→验证效果 完整流程 |
| 可视化 | 截图展示 | Mermaid 决策树 + 瓶颈定位流程图 |
| 过时工具 | Webpack Visualizer(已标记废弃) | 移除或降级为参考 |
Webpack 最大的优势在于它的功能非常强大、全面,加之繁荣活跃的组件生态,已经足够应对几乎所有 Web 构建需求,包括:SPA、MPA、SSR、桌面应用、Node 程序、WebAssembly、PWA、微前端等等,所以即使在近几年工程化领域异军突起、百花齐放的背景下,Webpack 也依然能保持老大哥的位置。
但软件世界没有银弹!Webpack 在大型项目中通常性能表现不佳,这一方面是因为 JavaScript 语言的单线程架构决定了 Webpack 的运算效率就不可能很高;另一方面则是因为在大型项目中,Webpack 通常需要借助许多组件(插件、Loader)完成大量的文件读写、代码编译操作。
幸运的是,站在开发者视角,我们有许多行之有效的性能优化方法,包括缓存、并发、优化文件处理步骤等,但在着手优化之前,有必要先简单了解一下 Webpack 打包的核心流程;了解哪些步骤比较耗时,可能会造成性能卡点;以及,如何借助一些可视化工具分析 Webpack 的编译性能。
Webpack 最最核心的功能,一是使用适当 Loader 将任意类型文件转译为 JavaScript 代码,例如将 CSS 代码转译为 JS 字符串,将多媒体文件转译为 Base64 代码等;二是将这些经过 Loader 处理的文件资源合并、打包成向下兼容的产物文件。
为了实现这些功能,Webpack 底层的工作流程大致可以总结为这么几个阶段:
entry 找出所有的入口文件,调用 compilation.addEntry 将入口文件转换为 dependence 对象。entry 文件开始,调用 loader 将模块转译为标准 JS 内容,调用 JS 解析器将内容转换为 AST 对象,从中找出该模块依赖的模块,再 递归 处理这些依赖模块,直到所有入口依赖的文件都经过了本步骤的处理;依赖关系图。Chunk;Chunk 施加一系列优化操作,包括:tree-shaking、terser、scope-hoisting、压缩、Code Split 等;在这个过程中有不少可能造成性能问题的地方:
构建阶段:
封装阶段:
splitChunks 配置、entry 配置、动态模块引用语句等,确定模块与 Chunk 的映射关系,其中 splitChunks 相关的分包算法非常复杂,涉及大量 CPU 计算;optimization 配置执行一系列产物优化操作,特别是 Terser 插件需要执行大量 AST 相关的运算,执行效率取决于 产物代码量。可以看出,Webpack 需要执行非常密集的 IO 与 CPU 操作,计算成本高,再加上 Webpack 以及大多数组件都使用 JavaScript 编写,无法充分利用多核 CPU 能力,所以在中大型项目性能通常表现较差。
不过,这些性能问题是可以被优化的!
有许多被反复实践、行之有效的构建性能优化手段,包括并行编译、缓存、缩小资源搜索范围等等,但在介绍这些具体的优化方法之前,有必要先聊聊:如何收集、分析 Webpack 打包过程的性能数据。
Webpack 从 v5 开始提供了更完善的内置分析能力,主要包括三大工具:
Stats 是 Webpack 内置的统计接口,专门用于收集模块构建耗时、模块依赖关系等信息。在 Webpack 5.107 中,stats 配置项得到了极大增强:
基本用法:
// webpack.config.js
module.exports = {
// 方式一:开启 profile 模式收集详细耗时数据
profile: true,
// 方式二:精细控制 stats 输出(推荐)
stats: {
// 基础选项
all: false, // 先关闭所有默认输出
assets: true,
errors: true,
warnings: true,
modules: true,
timings: true,
// 高级选项(v5 新增)
performance: true, // 显示性能提示
relatedAssets: true, // 显示关联资源
moduleTrace: true, // 显示模块追踪
dependencies: true, // 显示依赖关系
// 自定义输出格式
colors: true,
logging: 'warn', // 日志级别:'error' | 'warn' | 'info' | 'log' | 'verbose'
loggingDebug: [/webpack/], // 正则匹配需要详细日志的模块
}
}生成 stats.json 文件:
npx webpack --json=stats.json --profile也可以通过 Node API 获取 stats 数据:
const webpack = require('webpack');
const fs = require('fs');
const config = require('./webpack.config');
const compiler = webpack(config);
compiler.run((err, stats) => {
// 写入 JSON 文件
fs.writeFileSync('stats.json', JSON.stringify(stats.toJson({ source: false }), null, 2));
});stats.json 核心字段说明(v5.107):
{
"hash": "2c0b66247db00e494ab8",
"version": "5.107.0",
"time": 81,
"builtAt": 1620401092814,
"publicPath": "",
"outputPath": "/Users/project/dist",
"assetsByChunkName": { "main": ["index.js"] },
"assets": [
{
"name": "index.js",
"size": 12345,
"chunks": ["main"],
"emitted": true
}
],
"modules": [
{
"name": "./src/index.js",
"size": 1234,
"chunks": ["main"],
"reasons": [{ "moduleName": "main" }],
"profile": {
"factory": 10, // 模块工厂创建耗时(ms)
"building": 50, // Loader 编译耗时(ms)
"dependencies": 20, // 依赖解析耗时(ms)
"total": 80 // 总耗时(ms)
}
}
],
"chunks": [
{
"id": "main",
"names": ["main"],
"files": ["index.js"],
"size": 12345,
"modules": [...],
"origins": [...],
"rendered": true,
"initial": true,
"entry": true
}
],
"entrypoints": {
"main": {
"chunks": ["main"],
"assets": ["index.js"]
}
},
"timing": {
"building": 1000,
"dependencies": 500,
"total": 1500
},
"children": [
// 子 Compiler 数据(如 mini-css-extract-plugin)
],
// v5 新增字段
"namedChunkGroups": {},
"logging": {}
}关键洞察点:
modules[].profile:每个模块在各阶段的详细耗时,是性能优化的核心数据源chunks[].modules:Chunk 与 Module 的映射关系,用于分析分包策略assets[].size:最终产物体积,用于评估压缩效果children:子 Compiler 性能数据(如 CSS 抽取插件的独立编译过程)ProgressPlugin 是 Webpack 内置的进度显示插件,能够在编译过程中实时展示各阶段的进度:
const webpack = require('webpack');
module.exports = {
// ...
plugins: [
new webpack.ProgressPlugin({
// 基础配置
activeModules: false, // 显示活跃模块计数
entries: true, // 显示入口计数
modules: true, // 显示模块计数
modulesCount: 5000, // 模块最小显示阈值
dependencies: true, // 显示依赖计数
dependenciesCount: 10000, // 依赖最小显示阈值
// 进度回调(自定义输出)
handler: (percentage, message, ...args) => {
console.log(`${Math.round(percentage * 100)}% ${message}`);
},
// v5.107 新增选项
profile: false, // 收集性能剖析数据(用于后续分析)
}),
],
};典型输出示例:
0% compiling
10% building 0/1 entries 1/3 modules 0/3 dependencies
30% building 1/3 entries 5/15 modules 10/25 dependencies
60% building 1/3 entries 20/50 modules 30/80 dependencies
90% sealing 1/1 entries optimization
95% emitting
100% after emitting应用场景:
webpack-dashboard 是一个增强版的终端 UI 工具,比 ProgressPlugin 提供更丰富的实时信息:
安装与配置:
yarn add -D webpack-dashboardconst DashboardPlugin = require('webpack-dashboard/plugin');
module.exports = {
plugins: [
new DashboardPlugin({
// v5.107 支持的配置选项
port: 9838, // WebSocket 端口(用于远程监控)
host: 'localhost',
handler: undefined, // 自定义数据处理函数
// 传输层配置
transport: {
host: 'localhost',
port: 9838
}
}),
],
};启动方式:
npx webpack-dashboard -- webpack
npx webpack-dashboard -- webpack-dev-server
npx webpack功能特性:
基于 stats 数据,社区提供了众多优秀的可视化分析工具。下面我们按场景分类详细介绍:
⭐ 推荐指数:★★★★★(最常用)
webpack-bundle-analyzer 是社区使用率最高的性能分析工具之一,能够以交互式 Treemap 展示模块体积分布。
yarn add -D webpack-bundle-analyzer
npm install --save-dev webpack-bundle-analyzer// webpack.config.js
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
plugins: [
new BundleAnalyzerPlugin({
analyzerMode: 'server', // 默认值
analyzerHost: '127.0.0.1',
analyzerPort: 8888,
// 自动打开浏览器
openAnalyzer: true,
// 生成报告文件(可选)
generateStatsFile: false,
statsFilename: 'stats.json',
// 其他选项
reportTitle: 'Bundle Analysis',
defaultSizes: 'parsed', // parsed | gzip | brotli
logLevel: 'info',
}),
],
};特点:
new BundleAnalyzerPlugin({
analyzerMode: 'static',
reportFilename: 'bundle-report.html', // 输出到 dist 目录
openAnalyzer: false, // 不自动打开浏览器
})特点:
new BundleAnalyzerPlugin({
analyzerMode: 'disabled', // 禁用可视化界面
generateStatsFile: true,
statsFilename: 'bundle-stats.json', // 仅生成统计数据
})特点:
除了作为插件使用,还可以直接分析已有的 stats.json:
npx webpack-bundle-analyzer ./stats.json
npx webpack-bundle-analyzer ./stats.json -p 8888
npx webpack-bundle-analyzer ./stats.json -m static -r report.html基于 Bundle Analyzer 提供的视图,我们可以高效地分析出:
最佳实践建议:
--profile flag 收集更详细的性能数据⭐ 推荐指数:★★★★☆(定位慢速 Loader/Plugin 必备)
speed-measure-webpack-plugin 能够精确测量每个 Loader 和 Plugin 的执行耗时,帮助开发者快速定位性能瓶颈。
yarn add -D speed-measure-webpack-pluginconst SpeedMeasurePlugin = require('speed-measure-webpack-plugin');
const smp = new SpeedMeasurePlugin();
const config = {
entry: './src/index.js',
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader', 'postcss-loader'],
},
],
},
plugins: [
new HtmlWebpackPlugin(),
new MiniCssExtractPlugin(),
],
};
// 使用 smp.wrap 包裹整个配置
module.exports = smp.wrap(config); SMP ⏱ General output time took 3.24 mins
SMP ⏱ Plugins
MiniCssExtractPlugin took 0.001 mins
HtmlWebpackPlugin took 0.073 mins
SMP ⏱ Loaders
css-loader took 0.342 mins ⚠️ [slow]
module count: 456
postcss-loader took 0.567 mins ⚠️ [slow]
module count: 456
ts-loader took 1.234 mins ❌ [very slow]
module count: 789
babel-loader took 0.089 mins
module count: 123
SMP ⏱ External:
typescript compilation took 0.89 mins重要提示:Speed Measure Plugin 在 Webpack 5 中存在一些已知兼容性问题:
ESM 模块兼容性:部分 ESM-only 插件可能导致 smp.wrap() 失败
// 解决方案:使用 dynamic import 或配置 transpileOnly
const smp = new SpeedMeasurePlugin({
outputFormat: 'human', // 'human' | 'json'
outputTarget: process.stdout,
});Plugin 实例检测:某些特殊构造的 Plugin 可能无法正确识别
性能开销:该插件本身会轻微降低构建速度(约 5-10%),仅建议在性能排查时启用
替代方案:如果兼容性问题严重,可考虑使用:
webpack --profile + 手动分析 stats.jsonconst smp = new SpeedMeasurePlugin({
// 输出格式
outputFormat: 'human', // 'human' | 'json' | 'verbose'
// 输出目标
outputTarget: './smp-output.json', // 文件路径或 process.stdout
// 插件名称映射(解决匿名插件问题)
pluginNames: {
CustomPlugin: 'MyCustomPlugin',
},
// Loader 名称自定义
loaderNames: {
customLoader: 'my-custom-loader',
},
});⭐ 推荐指数:★★★★☆(复杂项目依赖分析神器)
Statoscope 是一个功能强大的 Webpack stats 可视化与分析工具,特别擅长实体间的关系分析。
yarn add -D @statoscope/cli
yarn add -D @statoscope/webpack-pluginconst StatoscopeWebpackPlugin = require('@statoscope/webpack-plugin').default;
module.exports = {
plugins: [
new StatoscopeWebpackPlugin({
// 基本配置
name: 'my-project', // 项目名称
saveTo: '.statoscope/report.webpack', // 报告保存路径
open: 'file', // 打开方式:'file' | 'server' | false
// 分析选项
analyzeMode: 'web', // 'web' | 'cli'
// 高级选项
watchMode: false, // 监听模式
additionalStats: [], // 额外的 stats 文件(用于对比)
context: __dirname, // 项目根目录
// 报告生成选项
disableReport: false,
reportOptions: {
keepName: false,
},
}),
],
};自动打开报告:
运行 npx webpack 后,Statoscope 会自动在浏览器中打开分析视图。
npx statoscope stats.json --open
npx statoscope before.json after.json --open
npx statoscope stats.json -o report.html多维度依赖关系图
重复包检测
体积分析与构成拆解
编译性能时间线
多版本对比(v5 新增)
⭐ 推荐指数:★★★☆☆(功能全面但上手难度较高)
Webpack Analysis 是 Webpack 官方提供的在线可视化工具,提供最全面的分析视角。
生成 stats.json:
npx webpack --json=stats.json --profile导入分析:
stats.json 文件| 面板 | 功能描述 |
|---|---|
| Modules | 模块列表、大小、依赖关系图 |
| Chunks | Chunk 组成、模块归属、加载方式 |
| Assets | 产物文件、体积、类型分布 |
| Warnings | 警告详情、优化建议 |
| Errors | 错误堆栈、位置定位 |
| Hints | 性能瓶颈提示(⚠️ 注意:暂不完全支持 Webpack 5) |
优势:
局限:
替代方案:
⭐ 推荐指数:★★★★☆(CI/CD & 自动化流水线必备)
webpack-stats-plugin 是一个轻量级插件,用于灵活地输出自定义格式的 stats 数据。
yarn add -D webpack-stats-pluginconst { StatsWriterPlugin } = require('webpack-stats-plugin');
module.exports = {
plugins: [
new StatsWriterPlugin({
filename: 'stats.json', // 输出文件名
fields: null, // null = 全部字段,或指定字段数组
stats: { // stats 配置选项(同 webpack.stats)
all: false,
assets: true,
chunks: true,
modules: true,
timings: true,
},
}),
],
};new StatsWriterPlugin({
filename: 'stats-transformed.json',
transform(data, opts) {
// 自定义数据转换逻辑
return JSON.stringify({
timestamp: Date.now(),
assets: data.assets.map(asset => ({
name: asset.name,
size: asset.size,
sizeKB: Math.round(asset.size / 1024),
})),
totalSize: data.assets.reduce((sum, a) => sum + a.size, 0),
chunkCount: data.chunks.length,
moduleCount: data.modules.length,
}, null, 2);
},
});CI/CD 性能基线监控
// 输出精简版 stats 用于对比
new StatsWriterPlugin({
filename: 'build-stats.json',
stats: { assets: true, timings: true },
})自动化测试集成
// 生成机器可读的结构化数据
new StatsWriterPlugin({
transform: (data) => JSON.stringify({
buildTime: data.time,
assetSizes: Object.fromEntries(
data.assets.map(a => [a.name, a.size])
),
})
})自定义 Dashboard 数据源
// 为内部平台提供标准化数据
new StatsWriterPlugin({
filename: '../dashboard/data/latest-build.json',
fields: ['assets', 'chunks', 'timings', 'hash'],
})⭐ 推荐指数:★★★★☆(团队协作 & PR Review 推荐)
bundle-stats 是一个专为 CI/CD 环境设计的 bundle 分析工具,能够生成易于分享的比较报告。
yarn add -D bundle-statsnpx bundle-stats
npx bundle-stats --path ./dist
npx bundle-stats --baseline ./baseline-stats.json --current ./current-stats.json
npx bundle-stats --format markdown > BUNDLE_REPORT.md
npx bundle-stats --format html > report.htmlconst { BundleStatsWebpackPlugin } = require('bundle-stats');
module.exports = {
plugins: [
new BundleStatsWebpackPlugin({
// 输出模式
mode: 'auto', // 'auto' | 'html' | 'markdown' | 'json'
// 对比基线(可选)
baseline: path.resolve(__dirname, '.bundle-stats/baseline.json'),
// 输出路径
outDir: '.bundle-stats',
// 报告文件名
filename: 'report',
// 自定义选项
jsonOutput: true,
showFiles: true,
showComponents: false,
}),
],
};
## Summary
- **Total Size**: 245 KB (-12% from baseline)
- **Chunks**: 3
- **Modules**: 156
## Assets Comparison
| Asset | Current | Baseline | Delta
| -------|---------|----------|-------
| main.js | 120 KB | 135 KB | -15 KB ✅ |
| vendor.js | 98 KB | 102 KB | -4 KB ✅ |
| runtime.js | 27 KB | 26 KB | +1 KB ⚠️ |
## Largest Modules
1. lodash (45 KB) - Consider tree-shaking or importing specific functions
2. moment (32 KB) - Consider using date-fns as alternative
3. @ant-design/icons (18 KB) - Consider importing only needed iconsname: Bundle Analysis
on: [pull_request]
jobs:
analyze:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install dependencies
run: yarn install
- name: Build project
run: yarn build
- name: Generate bundle report
run: npx bundle-stats --format markdown --baseline .bundle-stats/baseline.json
- name: Comment PR
uses: actions/github-script@v6
with:
script: |
const fs = require('fs');
const report = fs.readFileSync('.bundle-stats/report.md', 'utf8');
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `## 📊 Bundle Size Report\n\n${report}`
});⭐ 推荐指数:★★★★☆(重构清理必备)
unused-webpack-plugin 能够反向查找项目中未被使用的文件,特别适合代码重构场景。
yarn add -D unused-webpack-pluginconst UnusedWebpackPlugin = require('unused-webpack-plugin');
const path = require('path');
module.exports = {
plugins: [
new UnusedWebpackPlugin({
// 需要分析的源码目录
directories: [path.join(__dirname, 'src')],
// 项目根路径
root: path.join(__dirname),
// 排除规则
exclude: ['*.test.ts', '*.spec.ts', '__mocks__/**'],
// 包含规则(可选,默认所有文件)
include: ['**/*.ts', '**/*.tsx', '**/*.js'],
// 是否在失败时退出进程(CI 场景有用)
failOnUnused: false,
// 输出详细程度
verbose: false,
}),
],
};UNUSED FILES DETECTED:
❌ src/utils/deprecated-helper.ts
- Not imported by any module
- Last modified: 2026-01-15
❌ src/components/OldComponent.tsx
- Not imported by any module
- Consider removing or moving to archive/
✅ Total unused files found: 2no-unused-vars 规则双重保障Webpack 5 引入了强大的持久化缓存(FileSystem Cache),并提供专门的性能分析能力来评估缓存效果。
module.exports = {
cache: {
type: 'filesystem', // 使用文件系统缓存
// 缓存性能分析(v5 新增)
profile: true, // 记录缓存命中/未命中的详细信息
// 缓存目录
cacheDirectory: path.resolve(__dirname, '.cache/webpack'),
// 缓存版本(变更此值会清除旧缓存)
version: '', // 默认使用 webpack 版本
// 缓存算法
maxAge: 1000 * 60 * 60 * 24 * 7, // 7 天
maxGenerations: undefined,
// 构建依赖(变更会失效)
buildDependencies: {
config: [__filename],
},
},
};当开启 cache.profile: true 后,Webpack 会在控制台输出详细的缓存统计:
cached assets 5.02 MiB [compared for emit]
assets by path *.js 3.76 MiB
asset main.js 3.76 MiB [compared for emit] (name: main)
assets by path *.css 1.26 MiB
asset main.css 1.26 MiB [compared for emit] (name: main)
asset index.html 1.01 KiB [emitted]
// 缓存命中率统计
cache: cached 1234 modules (85% of total modules)
cache: not cached 217 modules (15% of total modules)
- 100 modules changed since last build
- 117 modules newly added
// 缓存恢复时间
cache: restored 1234 modules from filesystem cache (took 234ms)
cache: built 217 modules from scratch (took 1.2s)
// 总体效果
previous build time: 12.5s
current build time: 1.8s (85% faster due to cache)注意:这是一个实验性功能,需要在
experiments中显式启用
Webpack 5.107 引入了 experiments.cacheUnaffected 选项,用于缓存那些未被修改且不影响输出的模块:
module.exports = {
experiments: {
// 启用未受影响模块缓存
cacheUnaffected: true,
},
cache: {
type: 'filesystem',
profile: true,
},
};工作原理:
.d.ts)变更适用性判断:
npx webpack --profile --json=stats.json | jq '.modules[] | select(.unaffected == true)'合理设置 buildDependencies
buildDependencies: {
config: [__filename], // 配置文件变更会导致缓存失效
tsconfig: ['./tsconfig.json'], // TypeScript 配置变更
}避免频繁变动的依赖
监控缓存命中率
定期清理过期缓存
# 手动清除缓存
rm -rf .cache/webpack
# 或者在配置中设置合理的 maxAge下面的决策树可以帮助你根据具体场景选择最合适的分析工具:
| 场景 | 推荐工具 | 核心价值 |
|---|---|---|
| 首次接触性能优化 | Bundle Analyzer | 直观、上手快 |
| 构建速度慢 | Speed Measure Plugin | 精确定位瓶颈 |
| 复杂 Monorepo | Statoscope | 依赖关系全景 |
| PR Bundle 大小审查 | bundle-stats | 团队协作友好 |
| CI 性能基线 | webpack-stats-plugin | 自动化友好 |
| 代码重构 | Unused Plugin | 死代码检测 |
| 二次构建仍慢 | cache.profile | 缓存效果诊断 |
| 全面审计 | Webpack Analysis | 信息最全 |
下面是一个完整的性能优化方法论流程,帮助你系统地分析和解决问题:
webpack.config.js 中添加 profile: truenpx webpack --json=stats.json --profilestats.json 中的 time 字段modules[].profile 找出耗时最长的模块信号指标:
初步诊断方法:
npx webpack --profile --json=stats.json | jq '{time, hash, assets: (.assets | length), modules: (.modules | length)}'分层分析法:
| 层级 | 分析工具 | 关注指标 |
|---|---|---|
| 全局概览 | ProgressPlugin | 各阶段占比 |
| 模块级别 | Bundle Analyzer | 体积分布 |
| Loader 级别 | Speed Measure Plugin | 单次耗时 |
| 依赖级别 | Statoscope | 重复引用 |
| 缓存级别 | cache.profile | 命中率 |
对比维度:
验证脚本示例:
#!/bin/bash
echo "=== Webpack Build Benchmark ==="
rm -rf .cache/webpack dist
echo "\n🧊 Cold Build (no cache):"
time npx webpack --mode=production
echo "\n🔥 Hot Build (with cache):"
time npx webpack --mode=production
echo "\n🔥 Hot Build 2nd (cache stability):"
time npx webpack --mode=production
echo "\n📊 Generating analysis..."
npx webpack --mode=production --json=stats.json --profile
echo "\n✅ Benchmark complete!"| 问题现象 | 可能原因 | 推荐工具 | 解决方案 |
|---|---|---|---|
| 构建极慢(>2min) | Loader 链过长 | Speed Measure Plugin | 缩小 include/exclude 范围 |
| 产物体积过大 | 第三方库未优化 | Bundle Analyzer | external + CDN |
| 重复打包同一库 | 多版本依赖 | Statoscope | resolve.alias 统一 |
| 每次都全量重建 | 缓存未生效 | cache.profile | 检查 buildDependencies |
| 内存溢出 | 模块数过多 | stats.modules | Code Splitting + 动态导入 |
| TS 编译慢 | 类型检查阻塞 | Speed Measure Plugin | fork-ts-checker-webpack-plugin |
| CSS 处理慢 | PostCSS 插件多 | Speed Measure Plugin | 并行处理或缓存 |
| 图片资源大 | 未压缩/未转码 | Bundle Analyzer | image-webpack-loader |
这是一篇介绍 Webpack 性能分析的实践方法类文章(v2 全面升级版)。我们首先需要理解 Webpack 编译的基本过程,以及过程中各个步骤的耗时,理解哪些节点可能会消耗更多时间等,在此基础上我们才能更精确、有的放矢地排查出项目中的性能问题。
stats 配置项、ProgressPlugin、webpack-dashboard 三大内置工具webpack-stats-plugin、bundle-stats 两款现代化工具cache.profile 和 experiments.cacheUnaffected 专题理解基本原理后,你可以沿着上面的介绍,逐一试用、学习这些分析工具。建议的学习路径:
入门级(1-2天):
--profile,学会读取基础 stats 数据进阶级(3-5天): 3. 使用 Speed Measure Plugin 定位慢速 Loader 4. 尝试 Statoscope 进行依赖关系分析
专家级(1-2周): 5. 配置 CI 自动化报告(bundle-stats + webpack-stats-plugin) 6. 深入研究缓存机制(cache.profile + cacheUnaffected) 7. 建立团队性能基线和监控体系
记住:性能优化是一个持续的过程,而不是一次性的任务。建立科学的分析方法论,才能让优化工作事半功倍!
请仔细观察 stats 示例文件,思考几个问题:
进阶挑战:
4. 基于 cache.profile 输出,计算你的项目的缓存命中率,并尝试提升到 90%+
5. 使用 bundle-stats 生成一份 Markdown 报告,并在 PR 中展示优化成果
6. 设计一套适合你团队的 CI 性能监控方案(参考本章的方法论流程图)
| 工具名称 | 最新版本 | Webpack 5 支持 | 备注 |
|---|---|---|---|
| webpack-bundle-analyzer | ^4.10.x | ✅ 完全支持 | 推荐使用 |
| speed-measure-webpack-plugin | ^1.5.x | ⚠️ 部分兼容 | 需注意 ESM 问题 |
| @statoscope/webpack-plugin | ^5.x | ✅ 完全支持 | 功能强大 |
| webpack-dashboard | ^3.x | ✅ 完全支持 | 实时监控利器 |
| webpack-stats-plugin | ^0.3.x | ✅ 完全支持 | CI 自动化首选 |
| bundle-stats | ^0.19.x | ✅ 完全支持 | PR Review 友好 |
| unused-webpack-plugin | ^10.x | ✅ 完全支持 | 重构必备 |
| Webpack Analysis | 在线工具 | ⚠️ 部分 | Hints 功能受限 |
| ProgressPlugin | 内置 | ✅ 完全支持 | Webpack 5 原生 |
文档维护说明:本文档基于 Webpack v5.107 编写,随着 Webpack 版本迭代,部分 API 和工具可能会有所调整。建议关注各工具的 GitHub 仓库获取最新动态。