类库开发中避免破坏 tree shaking 的核心是确保导出可静态分析、无副作用、结构纯净:使用具名导出而非默认对象导出;入口文件不执行副作用;正确配置 package.json 的 module/main/sideeffects;避免装饰器,改用工厂函数或用户侧处理。

在类库开发中避免破坏 Tree Shaking,核心是让每个导出都保持“可静态分析、无副作用、结构纯净”。不是写得功能多就强,而是导出方式、构建配置和模块组织是否真正配合打包工具的摇树逻辑。
用具名导出代替默认导出对象
不要把多个函数塞进一个默认导出对象里:
❌ 不推荐export default { add, subtract, multiply };
这种写法会让使用者哪怕只写 import { add } from 'lib',打包工具仍可能保留整个对象——因为对象属性访问(obj.add)在某些转译或压缩场景下无法 100% 确定安全删除。
export const add = () => {};<br>export const subtract = () => {};<br>export const multiply = () => {};
每个函数独立声明、独立导出,工具能精确标记并剔除未引用项。
入口文件不执行、不注册、不修改全局
类库的主入口(如 index.js)应只做导出,不包含任何顶层副作用:
- 不调用
registerPlugin()、installVuePlugin()等初始化函数 - 不直接修改
window、globalThis或Reflect - 不自动注入样式(
import './styles.css')或 polyfill
有副作用的功能应拆到单独模块,由用户显式导入,例如:
import { createApi } from 'my-sdk';<br>import 'my-sdk/init'; // 明确副作用,便于 sideEffects 声明
正确配置 package.json 和构建输出
确保下游项目能识别并使用你的 ESM 版本:
- 设置
"module": "dist/index.es.js"(指向未转译/仅转译语法的 ES 模块) - 设置
"main": "dist/index.cjs"(兼容 CommonJS 环境) - 声明
"sideEffects": false—— 表示所有源文件无副作用;若部分文件有(如 CSS、polyfill),则写成数组:"sideEffects": ["./src/init.js", "./styles/*.css"]
同时在 Rollup/Vite 配置中输出 format: 'es',且 external 掉第三方依赖(如 lodash),避免它们被错误打包进去干扰摇树。
慎用装饰器与动态逻辑
装饰器(如 @Component、@inject)在类库中极易破坏 Tree Shaking:
- TypeScript 若设
target: "es5",装饰器会把整个 class 包进 IIFE,导致导出不可静态分析 - 装饰器常在定义时执行注册,产生顶层副作用,整块模块会被保留
替代方案:
- 升级编译目标为
es2022或更高,并启用useDefineForClassFields: true - 改用工厂函数:不写
export @memoize class A,而写export class A; export const memoizedA = memoize(A); - 将装饰逻辑移至用户侧,类库只提供纯类和可组合函数
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











