Tree Shaking 是构建工具在打包阶段基于 ES 模块静态结构分析并剔除未引用导出的优化机制,依赖静态可分析性和绑定不可变性,CommonJS 因动态特性不支持。

Tree Shaking 的核心不是 JavaScript 运行时行为,而是构建工具(如 Webpack、Rollup、Vite)在打包阶段基于 ES 模块的静态结构,通过静态分析识别并剔除未被引用的导出(export)和导入(import),从而移除“死代码”。它依赖于 ES Module 的两个关键特性:**静态可分析性** 和 **绑定不可变性**。
为什么只有 ES 模块支持 Tree Shaking
CommonJS(require/module.exports)是动态的:模块路径可以拼接、条件加载、运行时赋值,导致构建工具无法在编译期确定哪些导出真正被使用。而 ES 模块的 import 和 export 语句必须出现在顶层、路径必须是字符串字面量、导出名必须静态明确——这使得工具能精确追踪“谁导出了什么”、“谁导入了什么”、“哪些导出从未被读取”。
-
静态导入:不能写成
import('utils/' + name),否则该模块整体会被视为潜在使用,无法 shake -
具名导出需具名导入:如果只用
import { foo } from './utils.js',且foo确实被调用,那么bar、baz等其他导出才可能被安全剔除 -
避免默认导出的副作用陷阱:若
export default function () { console.log('init') }被导入但未调用,其执行仍会发生(因 import 本身会执行模块顶层代码),此时函数体不会被删,但未被调用的导出函数若无副作用,且未被任何变量/表达式引用,才可能被识别为“未使用”
静态分析如何判断“未使用”的导出
构建工具(如 Rollup)会构建一个模块依赖图,并对每个 export 做“引用计数”:从入口开始,顺着 import 向下遍历,记录每个导出名是否出现在某个 import 的导入列表中,或是否被赋值给全局变量、作为参数传入可能产生副作用的函数等。只要没有形成“可达路径”,该导出就被标记为 dead code。
-
不被 import 的命名导出:如
export const unused = 42;,且没有任何文件import { unused } from '...',则会被删除 -
被导入但从未读取的变量:如
import { helper } from './lib';但后续没出现helper()或console.log(helper),则helper的定义可能被删(前提是工具确认它无副作用) -
副作用感知很重要:若模块顶层有
console.log('side effect'),整个模块即使没被显式使用,也不能被完全剔除;可通过"sideEffects": false或"sideEffects": ["*.css"]在package.json中声明,帮助工具更激进地 shake
开发者需要做的关键配合
Tree Shaking 不是全自动魔法,它高度依赖代码写法和配置协同:
立即学习“Java免费学习笔记(深入)”;
-
始终使用 ES 模块语法:避免混用
require和import,尤其不要在同一个包里同时暴露 CJS 和 ESM 入口(除非明确指定exports字段区分) -
按需导入,而非星号导入:避免
import * as utils from './utils',这会让所有导出都变成“可能被使用”,无法 shake;改用import { debounce } from './utils' -
确保构建工具启用 production 模式:Webpack 需
mode: 'production';Rollup 默认启用;Vite 在 build 时自动生效 -
检查第三方库是否提供 ESM 版本:优先使用
lodash-es替代lodash,因为前者是纯 ESM,后者是 CJS 主入口,很难 shake
验证 Tree Shaking 是否生效
最直接的方式是查看最终打包产物(如 dist/ 下的 JS 文件)是否包含你确定没用的函数或常量。也可借助工具辅助分析:
- Webpack:启用
stats: 'verbose'或使用webpack-bundle-analyzer可视化模块构成 - Rollup:添加
treeshake: { moduleSideEffects: false, unknown: 'ignore' }并观察 warning - Vite:运行
vite build --report生成report.html查看各 chunk 内容 - 手动加
/*#__PURE__*/注释:对立即调用函数表达式(IIFE)等,可标注提示工具“此调用无副作用”,增强 shake 效果










