Tree Shaking 通过ES模块静态分析剔除未使用代码,减少压缩器输入体积;需用具名导出、避免动态导入、声明副作用、配合生产模式与Terser才能真正删除死代码。

Tree Shaking 本身不直接提升“压缩率”,而是通过精准剔除未使用的代码,显著减少输入到压缩器(如 Terser)的原始体积,从而让压缩器更高效地工作——最终包体积变小、效果更明显。关键在于 ES 模块(ESM)提供的静态可分析性,是整个机制成立的基础。
用纯 ESM 语法构建可分析的依赖图
ESM 的 顶层 import/export 强制声明让构建工具能在不运行代码的前提下,准确追踪每个函数、类或变量是否被引用。比如:
- ✅
import { debounce } from './utils.js'; export function debounce() {}→ 工具能确认只有debounce被使用 - ❌
const utils = require('./utils.cjs');或import('./feature.js')→ 动态行为切断分析链,整块代码被迫保留
导出颗粒化,避免默认导出大对象
如果一个模块写成 export default { debounce, throttle, deepClone },即使只用了 debounce,打包器也无法安全剔除其余两个——因为对象属性访问是运行时行为。正确做法是:
- 每个功能单独具名导出:
export function debounce() {}、export function throttle() {} - 入口文件做“巴氏分发”:
export { debounce } from './debounce.js';,保持引用路径清晰 - 调用端也用具名导入:
import { debounce } from './utils';,而非import utils from './utils'; utils.debounce
显式声明副作用,释放摇树空间
即使语法是 ESM,若模块顶层执行了 console.log()、修改 window 或注册全局事件,打包器会保守保留整个模块。解决方式:
立即学习“Java免费学习笔记(深入)”;
- 纯函数优先:导出内容不产生外部影响
- 在
package.json中设置:"sideEffects": false(全项目无副作用),或"sideEffects": ["*.css"](仅 CSS 有副作用) - 避免在模块顶层写执行语句,把副作用逻辑移到函数内部按需触发
配合生产模式与 Terser 真正删掉死代码
Tree Shaking 只负责“标记”未使用代码,真正物理删除靠压缩阶段:
- 确保构建在
mode: 'production'下运行(Webpack 默认启用usedExports和concatenateModules) - Terser 的
dead_code压缩选项会清除所有被标记为未使用的导出 - 可用
source-map-explorer验证最终 bundle,确认无用函数是否已消失


















