Tree Shaking 效果必须可测量、可验证、可拦截,CI 中需检查未使用导出残留率、整包导入误用、副作用干扰信号三项指标,并通过 source-map-explorer、webpack-bundle-analyzer、eslint-plugin-import 和 size-limit 等工具组合落地,嵌入构建后部署前阶段,失败则阻断 PR 合并。

Tree Shaking 效果不能只靠配置“相信它存在”,必须可测量、可验证、可拦截。在 CI 流程中集成检查,是防止体积劣化、保障长期优化成果的关键防线。
核心检查目标要明确
不是笼统说“有没有 Tree Shaking”,而是聚焦三个可量化指标:
- 未使用导出残留率:分析最终 bundle 中是否存在已声明但未被任何 import 引用的具名导出(如 utils.js 中 export function helper() {...} 却从未被调用)
- 整包导入误用:扫描源码中是否出现 import _ from 'lodash'、import * as echarts from 'echarts' 等高风险写法
- 副作用干扰信号:检查 package.json 是否缺失 "sideEffects" 字段,或该字段值为 true / undefined(等价于未声明),而非 false 或精确路径数组
CI 中可用的轻量级检查工具
无需引入重型构建,用静态分析+产物扫描组合即可落地:
- source-map-explorer:构建后生成可视化依赖图,CI 中可配合脚本提取特定模块的代码占比。例如:若 ./src/utils.js 在最终 bundle 中占 120KB,但实际只用了其中 2 个函数,就触发告警
- webpack-bundle-analyzer + 自定义校验脚本:在 CI 中运行 build --stats-json,再用 Node 脚本解析 stats.json,统计每个 module 的 providedExports 与 usedExports 差集。差集 > 0 即存在未摇掉的导出
- eslint-plugin-import + 自定义规则:启用 no-unused-modules 规则,直接扫描源码中未被引用的 export;搭配 import/no-unresolved 拦截错误路径,避免因路径错误导致误判“未使用”
- size-limit:声明关键模块的体积上限(如 “dist/index.esm.js should be
CI 流程中的嵌入方式
建议放在构建完成之后、部署之前,作为“体积守门员”阶段:
- 执行 npm run build(确保 mode=production,且 terser 压缩开启)
- 运行 size-limit 验证主入口体积是否超标
- 运行 npx source-map-explorer dist/bundle.js --json > stats.json,再用简单脚本检查 stats.json 中是否有模块的 exports 数远大于 usedExports 数
- 运行 eslint --ext .js,.ts src/ --rule '{"import/no-unused-modules": ["error", {"missingExports": true, "unusedExports": true}]}'
- 任意一项失败即 exit 1,阻断 PR 合并
配套的开发体验优化
光在 CI 拦截容易引发开发者抵触,需同步提供自助诊断能力:
- 在 package.json 的 scripts 中加入 "check:tree-shaking": "npm run build && npx source-map-explorer dist/bundle.js",供本地快速验证
- 提供预提交钩子(husky + lint-staged),在 git commit 前自动运行 eslint-plugin-import 检查,把问题拦在本地
- 在 CI 报告中给出具体修复指引,例如:“./src/api/client.ts 导出了 7 个函数,仅 2 个被引用;请确认是否应拆分模块,或检查是否遗漏 import”











