tree-shaking 起效的前提是全程使用 es modules:必须全链路采用 import/export、避免 commonjs、禁用动态导入与计算属性导出、优选具名导出而非 default 包裹对象,并确保第三方库提供 esm 入口。
要让 tree-shaking 真正起效,核心是让打包工具能“看懂”哪些代码没被用——而这个前提,就是整个模块链必须基于 es modules(esm)的静态结构。
确保所有模块都使用 import/export 语法
Tree-shaking 只对 ESM 生效,因为它的导入导出关系在编译时就固定了,工具可以逐层构建依赖图。一旦混入 CommonJS(比如 require 或 module.exports),静态分析就会中断。
- ✅ 正确写法:用 import { debounce } from 'lodash-es' 替代 const _ = require('lodash')
- ✅ 拆分导出:每个工具函数单独 export,而不是打包成一个对象再解构
- ❌ 避免 default export 包裹整个对象(如 export default { a, b, c }),这会让工具难以判断具体哪个属性被引用
避免破坏静态结构的写法
即使用了 import,某些动态行为也会让打包工具放弃分析,导致 Tree-shaking 失效。
- ❌ 不要在条件语句、函数体内或 try/catch 中写 import(ESM 要求顶层静态导入)
- ❌ 不要用计算属性名导出,如 export { [key]: value }
- ❌ 不要给 import 别名后又在运行时做二次赋值(如 import { foo as bar } from './x'; const fn = bar;),可能干扰引用追踪
配合构建工具正确启用和验证
Webpack、Vite、Rollup 默认开启 Tree-shaking,但需确认配置未意外关闭,且源码符合要求。
- 检查 package.json 中是否设了 "type": "module"(Node.js 环境下有助于统一解析规则)
- 使用 webpack-bundle-analyzer 或 Vite 的 --report 查看产物中是否还存在明显未调用的函数或工具类
- 留意第三方库是否提供 ESM 入口(如 lodash-es 而非 lodash),否则即使你写对了 import,库内部仍是 CJS,无法摇掉
导出方式影响摇树精度
不是所有 export 写法都一样友好。工具更擅长识别具名导出的细粒度引用。
- ✅ 推荐:export const a = 1; export function b() {} —— 每个导出独立可追踪
- ⚠️ 谨慎:export default { a, b } —— 整体被视为一个导出项,哪怕只用了 a,b 也可能保留在包里
- ✅ 更优:export * from './a'; export * from './b';(前提是被 re-export 的模块本身也符合 ESM 规范)










