tree shaking 效果需构建产物验证、代码结构审计与副作用控制三者结合:1. 人工比对产物体积与内容;2. 构造典型可摇样本;3. eslint 静态拦截风险模式;4. ci 自动化断言脚本。

Tree Shaking 的效果无法靠“写完代码就自动生效”来保证,它依赖构建工具(如 Webpack、Vite、Rollup)的静态分析能力,更关键的是——你的代码必须满足 ES Module 语法 + 无副作用的导出/导入结构。因此,“综合测试方案”的核心不是运行时检测,而是构建产物验证 + 代码结构审计 + 副作用控制三者结合。
1. 构建后产物体积与内容人工比对
这是最直接、最可信的验证方式。重点看未被引用的导出是否真的没进 bundle:
- 使用 --stats-json(Webpack)或 --report(Vite)生成构建报告,用 webpack-bundle-analyzer 可视化分析模块构成
- 打开最终生成的 .js 文件(如 dist/index.js),搜索你明确未使用的函数名、类名、常量名(如 unusedHelper、LegacyUtil),确认它们完全不存在
- 对比“启用 Tree Shaking”和“强制关闭”(如 Webpack 中设 optimization.usedExports: false)的产物大小差异,差距应显著(尤其在含大量工具函数的库中)
2. 编写可被摇掉的典型代码样本
构造一组覆盖常见易误判场景的测试用例,放入项目中并确保只导入其中一部分:
DMap GL地图JSAPI(dmapgl)开发指南。用于编写、审查、调试 DMap 地图 API 代码,涵盖地图初始化、覆盖物渲染、图层管理、事件处理、控件交互等任务。当用户提及 dmap、dmapgl、jsapi‑gl 或相关地图开发需求时自动触发。
- utils.js:导出命名函数、默认函数、具名常量、带副作用的初始化语句
- components.js:导出多个 React 组件(含高阶组件、自定义 Hook)、但仅在入口中 import { Button } from './components'
- api.js:导出多个请求方法(getUser, postOrder, deleteCache),但只调用一个
- 关键点:每个导出都加唯一标识字符串(如 // TREE_SHAKING_TEST: unusedHelper),便于 grep 快速定位残留
3. 静态检查 + ESLint 辅助拦截风险模式
很多 Tree Shaking 失败源于“看似纯 ES Module,实则含隐藏副作用”,需提前拦截:
- 启用 ESLint 插件 eslint-plugin-import,规则 import/no-unused-modules 可标出未被任何地方 import 的模块(虽非 Tree Shaking 直接等价,但能发现冗余文件)
- 禁用 export * from 'xxx'(会阻止具名导出的精确分析),改用显式重导出:export { a, b } from './x'
- 避免在导出语句外执行逻辑:console.log('init') 或 localStorage.setItem 等副作用代码必须包裹在函数内,否则整个模块会被视为有副作用而保留
4. 自动化断言脚本(CI 友好)
将验证步骤脚本化,集成进 CI 流程,防止回归:
- 用 Node.js 脚本读取构建后的 dist/*.js 内容,正则匹配预设的“应被摇掉的标识符”,断言其出现次数为 0
- 调用 rollup-plugin-visualizer 或解析 Webpack stats.json,提取某模块的 chunks 引用关系,断言未使用模块未出现在任何 chunk 的 modules 列表中
- 示例断言逻辑:expect(bundleCode).not.toMatch(/function unusedFeature/)










