tree shaking 能生效的关键在于函数被未引用、未导出、未调用,且模块系统确认其无副作用;必须使用 es 模块命名导出,避免默认导出和 commonjs,同时正确配置 package.json 的 "sideeffects" 字段。

Tree Shaking 能生效,关键不在于函数是否“纯”,而在于函数是否被标记为 无副作用(side-effect free),且其调用可被静态分析判定为“死代码”。纯函数声明本身不会自动触发 Tree Shaking;真正起作用的是:函数被 未引用、未导出、未调用,且模块系统(如 ES Module)能确认它对程序行为无影响。
函数必须是 ES 模块导出的命名函数
CommonJS 或默认导出的匿名函数很难被摇掉。Tree Shaking 依赖静态导入/导出语法,只有明确的 export function foo() {} 或 export const bar = () => {} 才可能被识别和剔除。
- ✅ 正确示例:命名函数 + 显式 export + 未被任何地方 import
- ❌ 无效示例:
module.exports = function() {}或export default () => {}(尤其当有运行时逻辑时)
函数体内不能有无法静态判定的副作用
即使函数逻辑上是纯的(比如只做计算),如果包含 console.log、localStorage、new Date()、或任何对外部状态的读写,打包工具(如 Webpack、Rollup)会保守地认为它有副作用,从而保留该函数——哪怕它没被调用。
- 避免在函数体中访问全局变量、修改闭包外变量、触发 DOM 操作
- 若必须保留某些“看似纯实则带副作用”的逻辑,可通过
/*#__PURE__*/注释手动标注(仅对立即调用有效,不适用于导出函数本身)
调用链必须完全可静态消除
Tree Shaking 是基于“引用图”进行剪枝的。只要一个函数被某个活代码路径间接引用(例如通过对象属性、数组索引、条件分支中的变量名),它就大概率保留在最终包中。
- 不要把导出函数赋值给动态键名对象:
const utils = { [mode]: myFunc }→ 摇不掉 - 避免通过字符串拼接或变量名反射调用:
someObj[funcName]() - 确保所有 import 都是字面量静态路径,且没有
import * as这类模糊引入
构建配置需启用并信任副作用声明
即使代码符合规范,若 package.json 中未设置 "sideEffects": false(或精确列出有副作用的文件),打包工具仍会为安全起见保留全部模块。
-
"sideEffects": false表示整个包内所有模块都无副作用,可放心摇 - 若部分文件含副作用(如 CSS 导入、polyfill),应显式列出:
"sideEffects": ["*.css", "src/polyfill.js"] - 确保使用支持 ES 模块解析的打包器版本(如 Webpack ≥ 4,Rollup 默认支持)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











