Tree Shaking 生效前提为 ES 模块且导出/导入静态可分析;重构需保持具名导出、避免动态逻辑与默认导出大对象,每次修改后须验证摇树效果。

Tree Shaking 能生效的前提是:模块必须是 ES 模块(ESM)语法,且导出/导入关系是 静态可分析的。模块重构时若破坏了这个前提,摇树就会失效。关键不是“怎么写新代码”,而是“怎么改旧代码时不踩坑”。
确保导出方式是静态、具名、无副作用的
重构时避免把多个导出合并成一个对象解构或动态导出:
- ❌ 不要这样改(破坏静态分析):
export const utils = { foo, bar };import { utils } from './utils.js';
→ 摇树无法识别utils.foo是否被用到,整个utils对象会被保留。 - ✅ 正确做法(保持具名导出):
export { foo, bar };import { foo } from './utils.js';
→ 打包器能明确知道只有foo被引用,bar可被安全移除。
避免在导出语句中引入运行时逻辑
重构时注意别把条件判断、函数调用、变量赋值塞进 export 行:
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
- ❌ 错误示例:
export const config = process.env.NODE_ENV === 'prod' ? prodConfig : devConfig;
→ 即使只用了config的某个字段,整个表达式因含环境判断而被视为有副作用,无法被摇掉。 - ✅ 推荐方式:
把逻辑移到内部,导出保持纯声明:const config = { /* 静态定义 */ };export { config };
慎用默认导出 + 解构重命名
默认导出本身不阻碍摇树,但和解构混用容易隐式引入未使用成员:
立即学习“Java免费学习笔记(深入)”;
- ❌ 重构后风险写法:
import Utils from './utils.js';const { foo, bar } = Utils;
→ 如果Utils是一个默认导出的对象(非 ESM 原生命名空间),打包器通常无法追踪其属性访问,导致全部保留。 - ✅ 更可靠的方式:
继续用具名导出,或确保默认导出是类/函数等单一实体(如export default class ApiClient { ... }),避免默认导出大对象。
验证重构后是否仍可摇树
别依赖直觉,每次重构后快速验证:
- 用
rollup --treeshake=verbose或 Webpack 的stats: 'verbose'查看哪些模块被标记为 “sideEffects: false”; - 构建后检查
dist目录产物,搜索未使用的导出名是否存在; - 临时删掉某个导出,看构建是否报错 —— 若不报错,说明它原本就没被引用,也印证摇树本该剔除它。

















