javascript tree shaking 需要 es modules,因为 es modules 强制要求导入和导出必须是静态的顶层声明,这使得打包工具能够在编译阶段通过抽象语法树(ast)分析精确识别代码中哪些部分被引用、哪些未被使用,从而安全地移除未引用的“死代码”。相比之下,commonjs 等动态模块系统在运行时才解析依赖关系,导致打包工具无法在构建时确定具体的引用路径,因此无法进行有效的静态分析。

为什么 CommonJS 无法支持 Tree Shaking
CommonJS 模块系统在执行 require() 时是动态执行的,它返回的是对象的一个浅拷贝。由于这种动态特性,打包工具无法在编译阶段确定模块导出的具体结构,只能保守地保留整个模块文件,导致 Tree Shaking 失效。

var _lodash = require('lodash');
// 实际执行时,_lodash 包含 lodash 的所有方法
// 即使只用了 map,其他方法也被引入并保留
var result = _lodash.map([1, 2], function(n) { return n * 2; });
console.log(result); // [2, 4]ES Modules 如何实现静态分析
ES Modules 使用 import 和 export 关键字,这些声明必须在模块的顶层,且不能包含动态逻辑。这种静态结构允许打包工具(如 Webpack 或 Rollup)在构建时直接读取 AST,明确知道哪些导出项被使用了,从而剔除未使用的代码。
立即学习“Java免费学习笔记(深入)”;

// index.js
import { map } from 'lodash-es';
// 只有 map 被标记为已使用
// 其他函数如 filter, forEach 会被标记为死代码并移除
const result = map([1, 2], (n) => n * 2);
console.log(result); // [2, 4]Tree Shaking 对纯函数的依赖条件
即使使用了 ES Modules,Tree Shaking 也依赖于代码必须是“纯函数”的假设。如果模块中存在副作用(如修改全局变量、调用外部 API),打包工具为了安全起见,通常会保留该模块,除非配置了特定的优化选项来覆盖这一行为。


















