【免费下载链接】webpack-bundle-analyzer
Webpack plugin and CLI utility that represents bundle content as convenient interactive zoomable treemap
webpack-bundle-analyzer 是 Webpack 生态中最流行的 bundle 可视化工具:它以交互式可缩放 treemap(矩形树图)呈现打包产物中每个 chunk、模块的真实体积,帮助开发者定位"哪些模块撑大了 bundle"。本文以仓库 CHANGELOG.md 为时间主线,完整梳理该插件从 1.2.5 到 5.3.1 的演进历程,并结合 src/ 与 client/ 下的源码,剖析每条变更背后的实现机制,让读者既能看到"改了什么",也能理解"为什么这样改、底层如何工作"。
项目定位:插件 + CLI 双形态的 bundle 分析器
在进入版本史之前,先明确这个项目的核心骨架。仓库根目录的 package.json 表明:项目以lib/index.js为入口、lib/bin/analyzer.js为命令行入口,同时提供两种使用方式:
- Webpack 插件:在 webpack 配置的
plugins中注册BundleAnalyzerPlugin,构建完成后自动产出分析报告(见 src/BundleAnalyzerPlugin.js)。 - CLI 工具:针对已生成的 stats JSON 文件离线分析,入口为 src/bin/analyzer.js。
两者共享同一套分析内核 src/analyzer.js 与渲染层 src/viewer.js,这也解释了为什么 CHANGELOG 中的大量改动能同时作用于插件与 CLI 两条路径。
5.x 时代:现代构建工具的适配与压缩算法扩展(5.0.0 ~ 5.3.1)
5.x 是当前仓库的稳定主线(最新版本 5.3.1),这一代的核心叙事是:跟上 Node.js 版本演进、扩展压缩算法、拥抱 Rspack 等新兴构建工具。
5.3.1:显式stats.toJson()选项,兼容 Rspack 2.0
5.3.1 的 Patch 变更中有两条值得关注:
- 显式定义
stats.toJson()选项以支持 Rspack 2.0。此前插件直接调用 webpack 的stats.toJson(),参数细节交给各构建工具自行兜底;Rspack 2.0 对默认 stats 输出的处理与 webpack 不同,若不显式指定选项,分析结果可能失真。现在插件内部定义了一份完整的analyzerStatsOptions(见 src/BundleAnalyzerPlugin.js#L34-L57),包含all: false、assets: true、cachedModules: true、chunks: true、chunkModules: true、nestedModules: true、entrypoints: true、source: false、runtimeModules: false等精确开关,并在server/static/json三种模式下统一以这份选项调用stats.toJson(analyzerStatsOptions)。这份选项清单同时明确了分析器的数据边界:只要 assets、chunks、modules、entrypoints 等字段,关闭源码、运行时模块与 warning/error 计数,从而降低 stats 序列化的体积。 - 修复 treemap 不响应 chunk 复选框选择的问题。前端状态层 client/store.js 中,
selectedChunks由复选框列表驱动,visibleChunks计算属性据此过滤出可见 chunk;本次修复确保了 treemap 的渲染数据与复选框状态强一致。
5.3.0:ECMA 新特性、propTypes 与 writeStats 竞态修复
- 代码使用新的 ECMA 特性:客户端组件开始采用更新的语法,同时为所有组件补齐
propTypes(见 client/components/types.js 中的zstdSize、parsedSize等类型定义),提升开发期类型自检能力。 - 修复
writeStats中的竞态条件:writeStats是 stats JSON 文件的写入函数,实现在 src/statsUtils.js#L94-L96,它通过自定义StatsSerializeStream(一个Readable流)逐层生成缩进格式化的 JSON,再经pipeline写入文件。旧实现对并发写入缺乏保护,可能导致stats.json内容错乱;当前实现基于 Node 内置stream/promises的pipeline,确保流在完成前不会被中断。
5.2.0:Zstandard 压缩支持
5.2.0 引入 Zstandard(zstd)压缩尺寸计算。压缩逻辑集中在 src/sizeUtils.js:
export const isZstdSupported = "createZstdCompress" in zlib; export function getCompressedSize(algorithm, input) { if (algorithm === "gzip") { return zlib.gzipSync(input, { level: 9 }).length; } if (algorithm === "brotli") { return zlib.brotliCompressSync(input).length; } if (algorithm === "zstd" && isZstdSupported) { return zlib.zstdCompressSync(input).length; } throw new Error(`Unsupported compression algorithm: ${algorithm}.`); }从源码可以推断出三点实现事实:
- zstd 依赖 Node.js 内建
zlib.createZstdCompress,因此该能力是运行时探测的:isZstdSupported为false时,CLI 的--compression-algorithm只会列出gzip、brotli两个可选值(见 src/bin/analyzer.js#L15-L17)。 - 模块级别的压缩尺寸在 src/tree/Module.js#L110-L122 中按需计算并缓存(
_zstdSize等私有字段),避免重复压缩。 - 前端侧,client/components/ModulesTreemap.jsx#L40-L42 依据
globalThis.compressionAlgorithm决定是否在尺寸切换器中展示 "Zstandard" 项。
同一版本还更新了sirv(静态资源服务器)与ws(WebSocket)依赖,这两者分别支撑报告页面的静态资源与 server 模式下的实时推送。
5.1.x:暗色模式与解析健壮性
- 5.1.0 新增可选暗色/亮色模式切换:主题状态由 client/store.js#L29-L42 管理,默认跟随系统
prefers-color-scheme,并持久化到localStorage;toggleDarkMode通过设置document.documentElement.dataset.theme切换主题。5.1.1 进一步修复了 CSS Modules 场景下暗色模式 tooltip 的样式问题。 - 5.1.1 避免 IIFE 形式 bundle 的解析失败:bundle 解析器 src/parseUtils.js 基于 acorn 识别模块包装器,IIFE 包装的 bundle 在早期版本中可能被误判;本次放宽了识别规则。
- 5.1.0 防止
assets/modules为undefined时抛TypeError:对应 src/analyzer.js#L122-L144 中getBundleModules对chunks?.map(...)与modules || []的防御性处理。
5.0.0:Breaking Change 与新能力集中落地
- Node 版本门槛升至 20.9.0 以上(见 package.json 的
engines字段)。对使用旧 Node 的项目而言这是升级 5.x 的硬性前提。 - 基于 stats JSON 信息按 ES Module 解析 bundle:
parseBundle调用处(src/analyzer.js#L287-L289)会根据statAsset.info.javascriptModule决定以"module"还是"script"模式解析,从而正确处理 ESM 语法特性。 - 新增 Brotli 压缩支持:
compressionAlgorithm参数从此支持gzip | brotli | zstd三选一。 - 新增 React Native 支持。
4.x 时代:Webpack 5、性能与依赖瘦身(4.0.0 ~ 4.10.2)
4.x 的关键词是规模化:适配 Webpack 5、应对超大 stats 文件,同时通过替换依赖把插件体积做到更小。
4.0.0:正式支持 Webpack 5
4.0.0 是 5.x 之前最重要的一次 Breaking Change:最低 Node 版本从 6/8 提升到 10.13.0,同时完成对 Webpack 5 的适配,并修复了在无浏览器处理程序的环境中设置openAnalyzer: true导致的崩溃。测试侧则引入"多 Webpack 版本并行测试"(仓库 package.json 的 devDependencies 中同时存在webpack(v5)与webpack-4两个包,可印证这一点)。
4.1.0 ~ 4.2.0:生成提速与依赖瘦身
- 4.1.0 显著加快
stats.json生成速度:即generateStatsFile: true时的写文件路径。核心实现为 src/statsUtils.js 的流式序列化方案——用一个生成器驱动的Readable流逐段产出 JSON,避免一次性JSON.stringify整个 stats 对象造成的大内存占用与卡顿。 - 4.2.0 连续三个 PR 削减依赖,并修复两类崩溃:webpack 数组配置(array config)生成的 bundle、以及
non-asset类型资源导致的解析失败(对应 src/analyzer.js#L254-L258 中对asset.type !== "asset"的过滤逻辑)。
4.3.0:用 Node 内置 HTTP 服务器替换 Express
这是架构层面的重要变化:移除 Express 依赖,改用 Node 原生http.createServer加sirv中间件(见 src/viewer.js#L147-L169),同时把filesize挪到 devDependencies。此后报告的依赖更少、启动更快,也为后续 5.x 的持续瘦身奠定了基础。
4.4.0 ~ 4.4.2:FoamTree 升级与健壮性修复
- 4.4.0 将 FoamTree(treemap 渲染库)升级到 3.5.0,并从 vendor 目录改为 NPM 包引入(现为 devDependencies 中的
@carrotsearch/foamtree);同时改进缩放动画期间标签的可见性,并修复悬停空白区域弹出空 tooltip 的问题。 - 4.4.1 修复模块 chunks 缺失(
missing module chunks)问题——仓库测试目录 test/stats/with-missing-module-chunks/ 即为该场景的回归样例。 - 4.4.2 修复
compiler.outputFileSystem.constructor为undefined时的崩溃。
4.5.0 ~ 4.6.0:发布瘦身、确定性颜色与 URL 定制
- 4.5.0 停止把
src目录发布到 npm,并在内部将 e2e 从 Nightmare 换为 Puppeteer、测试框架从 Mocha 换为 Jest(当前 jest.config.js 与 package.json 的test脚本可印证)。 - 4.6.0 新增两项能力:server 模式可输出自定义 URL(
analyzerUrl回调,见 src/BundleAnalyzerPlugin.js#L31 的类型定义与 src/viewer.js#L179-L183 的调用);chunk 颜色改为确定性生成,同一 chunk 在不同次报告中保持同色。4.6.1 修复 CLI 模式输出 URL 与预期不符的问题。
4.7.0 ~ 4.8.0:过滤能力与大文件支持
- 4.7.0 支持只显示每个 entrypoint 的 initial chunks:数据侧由 src/analyzer.js#L152-L168 的
getChunkToInitialByEntrypoint计算 chunk 与入口的归属关系,并在 src/analyzer.js#L424 以isInitialByEntrypoint字段输出。 - 4.8.0 支持读取超过 500MB 的 stats.json:读取端使用 @discoveryjs/json-ext 的
parseChunked流式解析(src/analyzer.js#L432-L434),写入端使用自定义序列化流,双向流式化使超大文件不再撑爆内存。 - 4.8.0 还优化了搜索体验:非匹配模块在视图中灰显(对应 client/store.js#L129-L141 的
searchQueryRegexp与前端高亮逻辑)。
4.9.0 ~ 4.10.2:细节完善与再瘦身
- 4.9.0:Webpack 5 下勾选 "Show content of concatenated modules" 时,展示拼接入口模块(concatenated entry module)的内部内容——对应 src/tree/ConcatenatedModule.js 的
fillContentModules与前端 client/store.js#L239-L260 的filterModulesForSize中的showConcatenatedModulesContent判断。 - 4.9.1 与 4.10.0:用 JavaScript 原生 API 替换
lodash.*系列包,显著缩小包体积;4.10.0 同时支持过滤 entrypoint 列表(getEntrypoints在 src/viewer.js#L58-L70 实现,前端据此生成入口过滤项)。 - 4.10.1 修复
this.handleValueChange.cancel()报错;4.10.2 修复.cjs文件未被正确处理的问题(对应 src/analyzer.js#L13 中FILENAME_EXTENSIONS正则包含js|mjs|cjs|bundle)。
3.x 时代:交互体验与输出模式成型(3.0.0 ~ 3.9.0)
3.x 定义了今天用户熟悉的报告界面形态:
- 3.0.0(Breaking):Node 最低版本提升到 6.14.4;拼接模块(concatenated modules)内容默认隐藏(可用侧边栏复选框开启);新增模块搜索、侧边栏固定/调整大小、侧边栏开关按钮等交互;内部状态管理引入MobX(延续至今,见 client/store.js)。同时视觉上合并"仅含单个子文件夹的嵌套文件夹",让树图更紧凑。
- 3.3.0:支持通过右键上下文菜单显示/隐藏 chunk。
- 3.4.0:新增
analyzerPort: 'auto'(由操作系统分配空闲端口,插件侧在 src/BundleAnalyzerPlugin.js#L101-L102 将auto归一化为端口0);并避免修改已生成的stats.json。 - 3.5.0 ~ 3.6.x:报告标题与 favicon 优化;支持
output.globalObject为'self'的构建;tooltip 可读性提升。 - 3.7.0:新增JSON 输出模式(插件
analyzerMode: "json",CLI--mode json),数据直接以 JSON 文件导出,便于 CI 流水线消费(实现见 src/viewer.js#L315-L338 的generateJSONReport)。 - 3.8.0:支持
WebWorkerChunkTemplatePlugin生成的 worker chunk,以及任意自定义globalObject(仓库 test/bundles/validWebpack4AsyncChunkUsingCustomGlobalObject.js 等测试 bundle 即为这些解析场景的样本)。 - 3.9.0:新增
reportTitle选项(默认输出格式化后的当前时间),并支持解析包含子资源(child assets)的 bundle。
2.x 时代:解析能力与实时更新的地基(2.0.0 ~ 2.13.1)
2.x 确立了"解析 minified bundle 得到真实 parsed 尺寸"这一核心卖点:
- 2.0.0:UI 完全重写(Preact + Webpack 2),新增gzip 尺寸展示与尺寸切换器;修复 CSS 模块等 asset 模块的尺寸计算。
- 2.1.0 ~ 2.5.0:新增
logLevel、defaultSizes选项、analyzerHost选项与--hostCLI 参数;支持output.jsonpFunction。 - 2.6.0 ~ 2.7.0:
defaultSizes正式落地;侧边栏新增 chunk 选择控制。 - 2.8.0:里程碑——支持
webpack --watch与 webpack-dev-server,源码变化后通过WebSocket自动更新模块树图。该机制沿用至今:src/viewer.js#L197-L228 中服务端在每次构建完成后调用updateChartData,向所有已连接客户端推送chartDataUpdated事件。2.8.2 大幅提升 gzip 尺寸精度,2.8.3 修复随机端口通告问题并支持 ESNext 语法解析。 - 2.9.0 ~ 2.11.0:侧边栏展示 chunk 尺寸;支持箭头函数模块包装器(对应 src/parseUtils.js#L44-L46 中同时接受
FunctionExpression与ArrowFunctionExpression);支持 Webpack 4 的 chunked modules 与拼接模块内容展示。 - 2.12.0 ~ 2.13.1:新增
excludeAssets选项;2.13.0 起放宽解析逻辑——无法解析或缺失的 chunk 不再导致整体失败,报告仍展示其余数据(这正是 README Troubleshooting 中"No bundles were parsed. Analyzer will show only original module sizes"提示的由来);2.13.1 将生成的 stats.json 改为带缩进的 pretty-print 格式(即 src/statsUtils.js 序列化器的行为)。
1.x 时代:功能奠基(1.2.5 ~ 1.5.4)
首个公开版本 1.2.5 之后,1.x 快速补齐了插件的基本能力:statsOptions选项(1.5.0)、static 报告模式(1.4.0)、startAnalyzer选项(1.3.0)、对DedupePlugin的兼容(1.4.x/1.5.2)、数组形式模块描述符的解析(1.5.2),以及将插件挂钩点从emit事件改为done事件(1.5.1)——后者正是当前 src/BundleAnalyzerPlugin.js#L168-L173 中compiler.hooks.done.tapAsync(...)的早期形态。
源码级原理:一条 stats 数据如何变成 treemap
将上述版本演进落到代码层面,完整链路如下:
- 收集 stats:插件在
done钩子中,以analyzerStatsOptions(5.3.1 起显式传入)调用stats.toJson(),得到StatsCompilation对象(src/BundleAnalyzerPlugin.js#L122-L166)。 - 过滤与解析:src/analyzer.js 的
getViewerData先剔除非js/mjs/cjs/bundle扩展名、无 chunk 归属、被excludeAssets命中的资源;若提供bundleDir,再对每个资源调用parseBundle(acorn + acorn-walk 实现的模块包装器识别,覆盖函数包装、DedupePlugin数组描述符、Array.concat优化等形式),从而得到 parsed 源码与 parsed 尺寸。 - 建树与压缩:模块按路径组织成
Folder树(src/tree/),由 src/sizeUtils.js 按compressionAlgorithm计算 gzip/Brotli/zstd 尺寸;模块级尺寸带缓存。 - 渲染与交互:src/viewer.js 依据模式(server/static/json)渲染 HTML 或写出文件;server 模式下通过
ws建立 WebSocket,构建重跑时推送新数据,前端 client/store.js 的 MobX store 驱动 chunk 过滤、搜索、尺寸切换与暗色主题。
升级关注点:Breaking Changes 汇总
根据 CHANGELOG,升级时需要重点检查的破坏性变更如下:
| 版本 | 破坏性变更 | 影响 |
|---|---|---|
| 5.0.0 | Node 最低版本提升至 20.9.0 | 旧 Node 环境无法运行 5.x |
| 4.0.0 | Node 最低版本 10.13.0;Webpack 5 支持 | 旧 Node 6/8 项目需先升级 Node |
| 3.0.0 | Node 最低版本 6.14.4;拼接模块内容默认隐藏 | 报告默认视图发生变化,需手动开启复选框 |
| 2.0.0 | UI 完全重写 | 侧边栏交互方式变化(鼠标移到左下角唤出) |
此外,5.2.0 引入的 zstd 能力有运行时前提:需要 Node.js 支持zlib.createZstdCompress(官方文档标注为 Node 22.15.0+)。当环境不满足时,CLI 会自动把--compression-algorithm的可选值收敛为gzip、brotli。
结语
纵观 CHANGELOG,webpack-bundle-analyzer 的版本演进呈现清晰的脉络:1.x 解决"能否分析",2.x 解决"分析得准不准 + 能不能实时",3.x 把交互体验打磨成熟,4.x 面向 Webpack 5 与超大规模项目做性能和依赖瘦身,5.x 则对齐 Node 20+、引入 Brotli/zstd 压缩算法并兼容 Rspack 2.0。对于使用者而言,理解这条演进线有助于在升级时精准评估 Breaking Change 的影响;对于想为该项目贡献的开发者,仓库中的 CONTRIBUTING.md、test/ 下的测试 bundle 与 stats 样例,则是研究其解析与渲染实现的现成教材。
【免费下载链接】webpack-bundle-analyzer
Webpack plugin and CLI utility that represents bundle content as convenient interactive zoomable treemap
相关推荐
Tremor Tooltip 组件演进全解析:从 changelog 版本变更到源码级实现原理
Tremor Tooltip 组件演进全解析:从 changelog 版本变更到源码级实现原理 Tremor 是用于构建图表与仪表盘的 React 组件库,而
UI组件图表库前端Plausible Analytics Tracker 演进全解:从 0.2.2 到 0.4.6 的版本变更与源码级实现原理
Plausible Analytics Tracker 演进全解:从 0.2.2 到 0.4.6 的版本变更与源码级实现原理 导读 本文以 Plausible
后端数据分析数据可视化Tinymce 表格模型引擎 Snooker 版本演进全解析:从 CHANGELOG 到源码级实现原理
Tinymce 表格模型引擎 Snooker 版本演进全解析:从 CHANGELOG 到源码级实现原理 导读 snooker 是 Tinymce 生态中负责 表
前端富文本
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考