javascript 模块支持 tree shaking 需满足:使用 es module 语法、显式声明无副作用(如 package.json 中 sideeffects: false)、避免聚合导出与动态行为(如 export *、require、字符串拼接 import)。

要让 JavaScript 模块支持 Tree Shaking,核心是让代码满足“静态可分析”条件:ES 模块语法 + 无副作用的导出/导入 + 避免动态行为干扰打包器判断。
使用 ES Module 语法(import/export)
Tree Shaking 依赖静态模块结构,CommonJS(require/module.exports)无法被 Webpack/Vite 等工具在构建时静态分析,因此必须用原生 import 和 export:
- ✅ 正确:export const foo = () => {};、export default class Bar {}
- ❌ 避免:module.exports = {...}、exports.xxx = ...、require('./x')
- ⚠️ 注意:即使用了 ES Module,若存在 export * from 'xxx'(重新导出),可能阻碍摇树,尤其当目标模块有副作用时
避免副作用干扰(side effects)
打包器默认假设模块有副作用(如执行全局逻辑、修改原型、发起请求),因此不敢删除看似未使用的导出。需显式声明无副作用:
- 在 package.json 中设置:"sideEffects": false(表示整个包无副作用)
- 或更精确地写:"sideEffects": ["*.css", "*.scss"](仅声明哪些文件有副作用,其余 JS 默认无)
- 避免在模块顶层写执行逻辑,例如:console.log('init')、localStorage.setItem(...)、Element.prototype.customMethod = ...
导出粒度合理,避免聚合式导出污染
一个常见反模式是创建 “index.js” 把所有功能一股脑 re-export:
- ❌ 不推荐:export { foo, bar, baz } from './utils'; export { A, B, C } from './components';(使用者哪怕只 import { foo },整个 utils 和 components 都可能被保留)
- ✅ 推荐:按功能拆分小模块,直接从源文件导入:import { debounce } from 'lodash-es/debounce';(注意用 lodash-es 而非 lodash)
- ✅ 或提供命名明确、职责单一的入口:export { default as Button } from './Button'; export { default as Input } from './Input';
避免“死代码”但被误判为“活代码”的写法
以下写法会让打包器保守保留代码,即使实际未调用:
- ❌ export const obj = { method() { ... } }; + 后续未访问 obj.method → 仍可能保留整个 obj(因属性访问不可静态判定是否被读取)
- ✅ 改为具名导出:export const method = () => {};
- ❌ const utils = { a: 1, b: () => {} }; export default utils;(default 导出对象难以摇树)
- ✅ 改用命名导出:export const a = 1; export const b = () => {};
- ❌ 动态 import() 中的字符串拼接:import(`./mod-${type}.js`) → 完全无法分析,禁用摇树
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











