核心是避免将多个功能打包进export default对象:✅具名导出(如export const fn = () => {})支持精准摇除;❌export default { a, b }会阻断tree shaking,因工具无法静态判定属性使用情况;⚠️default导出单个函数或类仍安全,但复合对象或动态结构不可摇。

避免 export default 导致 Tree Shaking 失效,核心是**不把多个功能打包进一个默认导出对象里**。ESM 的静态分析依赖具名导出(named export)的明确引用关系;而 export default { a, b, c } 这种写法会让打包工具无法判断你到底用了其中哪一个属性——它只能保守保留整个对象。
改用命名导出代替对象式 default
这是最直接有效的做法。每个函数、常量或工具单独导出,调用端也按需解构引入:
- ✅ 正确写法:
export const debounce = () => { /* ... */ };export const throttle = () => { /* ... */ };
使用时:import { debounce } from './utils.js'; - ❌ 错误写法:
export default { debounce: () => {}, throttle: () => {} };
使用时:import utils from './utils.js'; utils.debounce();—— 整个对象及未用方法都会被保留
若必须用 default,确保它是单个值而非聚合对象
default 导出本身不是问题,问题在于“导出什么”。只要 default 是一个纯函数、类或基础值,且没有隐式副作用,Tree Shaking 仍可生效:
- ✅ 可接受:
export default function myUtil() { return 'ok'; }或export default class ApiClient { ... } - ⚠️ 避免:
export default { helperA, helperB, config }、export default Object.assign({}, base, ext)等动态/复合结构
配合构建配置与第三方库选择
即使自己代码规范,外部依赖也可能破坏效果:
- 优先选用已做 ESM 拆分的库,如
lodash-es(每个函数独立导出),而不是lodash(默认 CommonJS + 聚合对象) - 在
package.json中设置"sideEffects": false,或精确列出有副作用的文件(如 CSS、polyfill),否则工具会因安全考虑保留整块模块 - 确认 Babel 不转译 ESM:在
@babel/preset-env中设modules: false,防止export被编译成Object.defineProperty(exports, ...),切断静态分析链
验证是否真正生效
别只看配置,要查最终产物:
- 执行生产构建(如
npm run build),打开dist/下生成的 JS 文件 - 搜索某个明确未使用的函数名(如
subtract),确认它在 bundle 中完全不存在 - 用
source-map-explorer或rollup-plugin-visualizer可视化依赖图,定位残留模块来源
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











