Tree Shaking 不处理条件编译代码剔除,仅基于静态 ESM 导入导出做死代码消除;条件编译需构建工具配合预处理器先替换(如 DefinePlugin 将 process.env.NODE_ENV 替换为字面量),再由 Terser 等压缩器删除恒假分支。

Tree Shaking 本身不处理条件编译代码的剔除,它只基于静态的 ES 模块导入导出关系做“死代码消除”。条件编译(比如用 process.env.NODE_ENV 或自定义宏)属于运行时或构建时逻辑,需要构建工具(如 Webpack、Vite、Rollup)配合预处理器(如 Babel、esbuild)先完成替换,再让 Tree Shaking 生效。
Tree Shaking 的前提:ESM 静态结构
Tree Shaking 要求模块使用 import/export(ESM),且导出/导入语句不能是动态的(如 import() 或拼接字符串的 require)。它通过分析 AST 判断哪些导出从未被引用,从而剔除未使用的导出及依赖链上的副作用-free 代码。
- 如果一个函数只在
if (false)块里被调用,但该if是运行时判断,Tree Shaking 不会删——因为 AST 中它仍是“可达”的 - 只有当代码被**提前移除**(如宏替换后变成纯不可达语句),后续的压缩器(如 Terser)才可能进一步删掉无用分支
条件编译需靠构建阶段“展开”
真正实现“按环境剔除条件分支”,靠的是构建工具在打包前把条件判断替换成字面量,让死代码暴露出来。例如:
if (process.env.NODE_ENV === 'development') {
console.log('debug');
}
经 Define 插件(Webpack 的 DefinePlugin、Vite 的 define)处理后变成:
Java开发手册规约集合,基于阿里巴巴Java开发手册(嵩山版)。 涵盖7大维度:编程规约、异常日志、单元测试、安全规约、MySQL数据库、工程结构、设计规约。 当用户需要:(1) 编写或审查Java代码 (2) 检查命名/代码规范 (3) 处理异常和日志 (4) 编写单元测试 (5) 安全编码 (6) 数据库设...
立即学习“Java免费学习笔记(深入)”;
if ('production' === 'development') {
console.log('debug');
}
再经 Terser 压缩,就会直接删掉整个 if 块(因为条件恒假)。
- 确保
process.env.NODE_ENV等变量被正确内联为字符串字面量,而非保留为对象访问 - 自定义宏(如
__DEV__)也要用相同方式定义,避免运行时取值 - Vite 默认开启 define 和 minify,Webpack 需配
mode: 'production'+DefinePlugin+ TerserPlugin
避免阻断 Tree Shaking 的写法
即使条件已展开,某些写法仍会让代码“逃过”剔除:
- 导出一个对象,其中部分属性只在某环境下使用,但整个对象被导入 → 改成按需导出独立函数/常量
- 模块有副作用(如顶层执行
console.log、修改全局)→ Tree Shaking 不敢删,需加/*#__PURE__*/注释或设sideEffects: false - 使用
require或动态import()加载模块 → 这些路径无法静态分析,Tree Shaking 失效
验证是否生效的小技巧
不是看源码有没有 if,而是检查最终产物中是否还存在对应逻辑:
- Webpack:启用
stats: 'verbose',查看usedExports和providedExports - Vite:构建后用
vite build --report生成模块依赖图,或直接查 dist 输出中的 JS 文件 - Terser 可加
compress: { drop_console: true }主动删日志,作为补充手段

















