tree shaking 依赖 es 模块(esm)的静态语法结构,通过 import/export 在编译时确定依赖关系,由 webpack、rollup 等构建工具在生产模式下静态分析并移除未引用代码。

模块执行上下文本身不直接实现 Tree Shaking,真正起作用的是 ES 模块(ESM)的静态语法结构。所谓“模块执行上下文支持 Tree Shaking”,实质是指 ESM 的设计让构建工具能在编译阶段准确分析依赖关系——这是 Tree Shaking 能落地的前提。
必须使用 ES6 import/export 语法
Tree Shaking 依赖静态可分析性:import 和 export 必须出现在顶层作用域,路径和标识符必须是静态字符串。这样构建工具(如 Webpack、Rollup、Vite)才能在不运行代码的情况下,确定哪些导出被引用、哪些未被使用。
- ✅ 正确示例:
import { debounce } from './utils.js';—— 导入目标明确,可追踪 - ❌ 无效写法:
const utils = require('./utils.js');或if (condition) { module.exports = {...} }—— CommonJS 动态赋值,无法静态判定导出内容
构建工具需启用生产模式或显式配置
即使代码符合 ESM 规范,若构建工具未开启相关优化,Tree Shaking 也不会触发。
- Webpack 中,
mode: 'production'会默认启用usedExports和minimize - 开发模式下也可手动开启:
optimization.usedExports: true+ 配合 Terser 压缩器清理标记代码 - Rollup 默认启用且效果更彻底;Vite 在 build 阶段自动应用
模块不能有隐式副作用
如果模块在顶层执行了修改全局变量、调用 API、操作 DOM 等行为,构建工具为安全起见会保留整个模块,即使其中某些导出未被引用。
- 可通过
package.json中的"sideEffects": false声明该包无副作用 - 若仅部分文件有副作用(如 CSS 导入、初始化脚本),可精确列出:
"sideEffects": ["*.css", "init.js"] - 避免在模块顶层写立即执行逻辑,例如:
console.log('init');或window.myLib = {};
导出内容需可被独立引用和标记
每个 export 必须是具名、静态、不可覆盖的,才能被单独标记为“已使用”或“未使用”。
- ✅ 支持摇树:
export function foo() {}、export const BAR = 42; - ⚠️ 风险写法:
export default { foo, bar };—— 整个对象可能被当作一个单元保留 - ❌ 不支持:
export {}动态拼接、if (...) { export ... }条件导出(ESM 不允许)











