Tree Shaking 是一种基于 ES 模块静态分析的死代码消除技术,只对 import/export 生效,不支持 CommonJS;需配置 production 模式、sideEffects、usedExports 等,并避免动态导入和假聚合入口。

Tree Shaking 不是靠死记配置就能掌握的,关键在于理解它“为什么能摇、怎么摇、为什么没摇掉”这三层逻辑。复习时抓准核心,避开常见误区,效率会高很多。
搞懂它只对 ES 模块生效
Tree Shaking 的前提是静态分析,而只有 ES6 import/export 是编译时确定的。CommonJS(require/module.exports)在运行时才决定加载什么,打包工具根本没法提前判断哪些导出没被用——所以它天然不支持 Tree Shaking。
- 检查你用的库是否提供 ESM 版本(比如 lodash-es 而非 lodash)
- 自己写的工具模块,别用 export default + require 混搭,统一用命名导出 + 静态 import
- Babel 配置里必须设 modules: false,否则会把 import 编译成 require,直接废掉 Tree Shaking
看清打包工具的“默认开关”
Webpack 从 v4 开始,在 mode: 'production' 下自动启用基本 Tree Shaking,但只是“基础版”。真正要让它精准工作,还得手动确认几项:
- usedExports: true(标记哪些导出被使用)
- minimize: true(压缩阶段配合剔除)
- sideEffects: false 或精确声明副作用文件(比如 CSS、JSON、有全局副作用的 JS),否则整个模块会被保留
Rollup 默认更激进,Vite 基于 Rollup 内核,开箱即用效果通常更好。
使用约定式提交(Conventional Commits)生成标准化的 Git 提交信息。适用于以下场景: (1) 暂存更改时需要提交信息; (2) 审查 diff 时希望获得结构化摘要; (3) 编写 PR 描述或变更日志(changelog)条目; (4) 用户明确要求“为本次更改编写提交信息”。 该功能会分析已暂存/未暂存的 diff,并生成按类型(type)划分范围的提交信息。
验证它到底有没有起作用
别光看 bundle 大小变化,那可能是压缩或其它优化带来的。要真确认 Tree Shaking 生效,得看具体函数是否真的被删了:
- 用 Webpack 的 stats: 'verbose' 或 webpack-bundle-analyzer 查看模块内部哪些 export 被标记为 “unused”
- 写个极简测试:一个文件导出两个函数,只 import 其中一个,在生成代码里搜另一个函数名,应该完全找不到
- 注意动态 import() 和 eval、with 这类运行时行为,会阻断静态分析链,导致整块模块无法被 shake
警惕“假模块入口”陷阱
很多项目在 utils/ 目录下放一个 index.js,里面写 export * from './a'; export * from './b';。这种写法会让打包工具认为所有子模块都被“可能用到”,哪怕你只 import { foo } from './utils',整个 utils 目录也可能全被打包进来。
- 优先用“直接路径导入”:import { debounce } from 'lodash-es/debounce'
- 如果必须用聚合入口,index.js 里改用具名重导出,避免 export *
- 搭配 package.json 的 exports 字段(Node.js 12.20+),可让工具精准定位 ESM 入口










