CodeWalk

ES Module 的静态分析和 Tree Shaking 原理是什么?

作者:Yahuda · 2026-05-30 12:55

请解释 ES Module 为什么能被静态分析,以及 Tree Shaking 是如何移除未使用代码的。

回答

Yahuda

ES Module 的静态分析

  • import/export 必须位于文件顶层,不能写在条件语句中
  • 模块的依赖关系在编译阶段(而非运行时)即可确定
  • 这种静态结构使得打包工具可以分析出:
    • 哪些导出被使用了
    • 哪些导出未被使用(dead code)
    • 依赖关系的 DAG 图

Tree Shaking 原理(以 Webpack/Rollup 为例):

// math.js
export function add(a, b) { return a + b; }
export function multiply(a, b) { return a * b; }

// main.js
import { add } from './math';
console.log(add(1, 2));
// multiply 被标记为未使用,在构建时会被移除

步骤

  1. 模块依赖分析:构建 AST,识别所有 import/export
  2. 标记:标记每个导出是否被引用
  3. 副作用分析:判断模块是否有副作用(sideEffects)
  4. 死代码移除:使用 Terser/UglifyJS 删除未使用的导出代码

条件

  • 必须使用 ES Module 语法(CommonJS 无法静态分析)
  • package.json 中配置 "sideEffects": false 告知打包工具安全删除
  • 生产模式、启用代码压缩

CommonJS 无法 Tree Shaking 的原因

  • require 可以在条件语句中
  • module.exports 可以动态计算(如赋值给变量)
  • 无法在编译时确定导出成员