javascript tree shaking 正常工作的关键是esm静态导出与无运行时动态行为,而非仅写纯函数;需确保具名静态导出、顶层无副作用、调用链可静态追踪,并合理配置sideeffects。

要让 JavaScript 的 Tree Shaking 正常工作,关键不是“写纯函数”本身,而是确保模块导出和调用方式满足静态可分析性要求。纯函数只是辅助条件——它能减少副作用,但 Tree Shaking 能否生效,根本取决于 ESM 语法结构 和 无运行时动态行为。
导出必须是静态的、具名的、无条件的
Tree Shaking 工具(如 Webpack、Rollup、Vite)依赖静态 AST 分析,无法处理动态导出或运行时逻辑。
- ✅ 正确:直接具名导出函数,且不包裹在条件、变量或 IIFE 中
export const utilsB = () => 'b';
- ❌ 错误:导出被赋值给变量、条件判断、或通过对象属性动态挂载
export default obj; // 摇不掉
if (process.env.NODE_ENV === 'dev') {
export function debugHelper() {} // 静态分析无法确定是否导出
避免副作用表达式污染模块顶层作用域
即使函数本身是纯的,如果模块顶层有执行逻辑(如 console、fetch、修改全局、new Date()),打包器会认为该模块有副作用,整个模块都可能被保留。
- 把副作用操作移到函数内部(只要该函数未被引用,仍可被摇掉)
- 在
package.json中显式声明"sideEffects": false或精确列出有副作用的文件(如["*.css", "index.js"]) - 不要在模块顶层写:
console.log('init')、localStorage.getItem()、new Promise()等
调用链必须可静态追踪(禁止动态引用)
即使导出是静态的,如果导入后用字符串拼接、数组索引、或变量访问函数,Tree Shaking 就会失效。
- ✅ 正确:直接调用具名导入
utilsA(); // 可被识别,未调用则可摇掉
- ❌ 错误:通过动态键、eval、with、或间接引用绕过静态分析
utils['utilsA'](); // 模块所有导出都被标记为已使用
const key = 'utilsA';
utils[key](); // 同上
纯函数有助于提升可摇性,但不是充分条件
纯函数(无副作用、输入决定输出)本身不会触发 Tree Shaking,但它能降低误判风险:
- 没有全局状态依赖 → 不会因“可能影响其他模块”而被保守保留
- 没有外部 I/O → 不会被打包器归类为“不可摇动的副作用模块”
- 更容易被内联(inlining)或进一步优化,间接增强摇树效果
不过,一个纯函数若被静态导入且被调用,照样不会被摇掉;反之,一个非纯函数只要没被静态引用,且模块无副作用,依然可以被摇掉。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











