Tree Shaking 摇的是未被 import 和调用的 ES6 导出内容,需满足静态导入、正确导出、无顶层副作用、生产模式构建及 sideEffects 配置,并通过打包分析验证效果。

Tree Shaking 不是靠“背教程”学会的,而是靠理解原理 + 写对代码 + 配对工具 + 看得见效果,四步闭环练出来的。下面直接说实用路径,不绕弯。
一、先搞懂它到底在摇什么
Tree Shaking 摇的是模块中没被 import 过、也没被调用过的导出(比如函数、常量、类)。不是摇变量,不是摇注释,更不是摇 console.log——它只认 ES6 的 静态 import/export 结构。
关键判断点:
- 用
import { debounce } from 'lodash'→ 可能摇掉其他函数; - 但用
import _ from 'lodash'或const _ = require('lodash')→ 整个库大概率全留下; - 哪怕函数本身是纯的,如果模块顶层写了
console.log('init')或localStorage.setItem()→ 整个模块会被当成“有副作用”,拒绝摇动。
二、代码怎么写才真能被摇
重点不在“函数是否纯”,而在导出是否静态、调用是否可追踪、顶层是否干净:
- ✅ 正确导出:
export function foo() {}、export const bar = () =>{}; - ❌ 错误导出:
const utils = { foo }; export default utils(动态对象,摇不动); - ✅ 正确调用:
import { foo } from './a.js'; foo();; - ❌ 错误调用:
import * as a from './a.js'; a['foo']();(运行时索引,分析不出); - ⚠️ 顶层清零:删掉所有
fetch()、new Date()、document.body.appendChild()等副作用表达式,挪进函数里再用。
三、构建配置要配齐这三样
缺一不可,否则 Tree Shaking 就是“开着门却锁着窗”:
- 模式必须是 production:Webpack/Vite/Rollup 默认只在生产模式下启用深度摇动;
-
Babel 不能转成 CommonJS:配置
{"presets": [["env", {"modules": false}]]},保留原生export; -
package.json 加 sideEffects 字段:设为
"sideEffects": false(表示全模块无副作用),或精确列出有副作用的文件,如"sideEffects": ["*.css", "index.js"]。
四、验证有没有真摇成功
别信配置,要看结果:
- 用
webpack-bundle-analyzer打开打包产物,搜索你没用的函数名,看是否还在 bundle 里; - 在源码里加一个明显不会被调用的函数(比如
export function __DEBUG_ONLY__() {}),然后 build,检查它是否消失; - 对比开启/关闭
sideEffects: false前后体积变化——差值大,说明摇对了;差值小,大概率卡在某处没摇动。











