构建支持 Tree Shaking 的通用工具库需遵循以下核心原则:使用 ESM 语法、避免副作用、合理配置打包格式,并通过验证确保未引用代码被移除。 具体步骤如下:
1. 使用 ES 模块语法- 避免 CommonJS:Tree Shaking 依赖静态分析,必须使用 import/export 语法,而非 require/module.exports。动态导入(如 import())或混用 CommonJS 会导致失效。
- 模块拆分:每个工具函数单独定义在一个文件中,使用命名导出(export),而非默认导出或命名空间导出。例如:javascript // src/utils/format.js export function formatDate(date) { /* ... */ } export function formatNumber(num) { /* ... */ }
- 入口文件重新导出:在入口文件(如 src/index.js)中通过命名导出聚合所有功能:javascript export * from './utils/format'; export * from './utils/validate';
2. 避免副作用- 副作用定义:副作用指模块执行时除导出值外的其他行为(如修改全局变量、执行 console.log、动态加载资源等)。打包工具默认保留有副作用的模块。
- 声明无副作用:在 package.json 中设置 "sideEffects": false,告知打包工具整个库无副作用,可安全删除未引用代码。例如:json { "name": "my-utils", "main": "dist/my-utils.cjs.js", "module": "dist/my-utils.esm.js", "sideEffects": false }
- 处理真实副作用:若库包含 CSS 引入或 polyfill 等副作用,需在 sideEffects 数组中明确列出文件路径:json "sideEffects": ["./src/polyfill.js", "*.css"]
3. 合理配置打包输出格式- 多格式输出:为兼容不同环境,同时输出以下格式:- ESM(.esm.js):保留静态 import/export,供支持 Tree Shaking 的工具(如 Webpack、Rollup)使用。- CommonJS(.cjs.js):供 Node.js 或旧版工具使用。- UMD(可选):用于浏览器直接引入(需全局变量)。
- 推荐工具:使用 Rollup 或 Vite 打包,它们天然支持 Tree Shaking。示例 Rollup 配置:javascript // rollup.config.js export default [ { input: 'src/index.js', output: { file: 'dist/my-utils.esm.js', format: 'esm' } }, { input: 'src/index.js', output: { file: 'dist/my-utils.cjs.js', format: 'cjs' } } ];
- 配置说明:- input:入口文件路径。- output.file:输出文件路径。- output.format:模块格式(esm/cjs/umd)。
4. 验证 Tree Shaking 效果- 手动测试:1. 创建测试项目,仅引入库中的某个函数:import { formatDate } from 'my-utils';
2. 使用 Webpack 或 Vite 构建项目,检查生成的 `bundle` 文件,确认未引用的函数(如 `formatNumber`)未被包含。- 工具分析:- 使用 webpack-bundle-analyzer 分析打包体积,直观查看未使用的代码是否被移除。- 检查打包工具的警告信息(如 Webpack 的 unused harmony export 提示)。
5. 其他优化建议- 代码规范:- 避免在模块顶层执行代码(如直接调用函数),所有逻辑应封装在函数或类中。- 避免使用 eval 或 new Function(),这些会阻止静态分析。
- 文档说明:在库的 README 中明确声明支持 Tree Shaking,并指导用户如何配置打包工具(如设置 optimization.usedExports: true)。
示例项目结构my-utils/├── src/│ ├── utils/│ │ ├── format.js # 导出 formatDate, formatNumber│ │ └── validate.js # 导出 validateEmail, validatePhone│ └── index.js # 重新导出所有工具函数├── dist/│ ├── my-utils.esm.js # ESM 格式│ └── my-utils.cjs.js # CommonJS 格式├── package.json└── rollup.config.js通过以上步骤,可确保工具库的未使用代码在构建时被静态分析工具移除,从而优化最终打包体积。