Tree-Shaking
Tree-Shaking 是前端工程化中一种用于消除无用代码(Dead Code) 的优化技术,其核心目的是在打包过程中剔除项目中未被使用的代码,从而减小最终输出文件的体积。
核心原理
Tree-Shaking 的实现依赖于 ESM(ECMAScript Module)的静态模块结构:
ESM 采用
import/export语法,模块依赖关系在编译时(静态分析阶段) 就能确定,而非运行时。工具(如 Webpack、Rollup、Vite 等)通过静态分析,识别出哪些导出的变量/函数从未被导入使用,这些就是“无用代码”。
最终打包时,这些未被使用的代码会被直接剔除,如同从树上摇掉枯叶(“摇树”因此得名)。
关键前提
必须使用 ESM:
CJS(CommonJS)是运行时动态加载(require可写在条件语句中),无法在编译时确定依赖关系,因此不支持 Tree-Shaking。代码需处于“严格模式”语境:
ESM 模块默认运行在严格模式下,避免了一些动态语法(如eval、修改arguments等)对静态分析的干扰。导出需为“具名导出”(Named Export):
默认导出(export default)通常是一个对象,工具难以精确判断对象内部哪些属性未被使用,因此 Tree-Shaking 对具名导出的优化更彻底。
示例说明
假设存在一个模块 utils.js:
// utils.js(ESM)
export const add = (a, b) => a + b;
export const minus = (a, b) => a - b;
在另一个文件中仅导入 add:
// app.js(ESM)
import { add } from './utils.js';
console.log(add(1, 2)); // 仅使用 add,未使用 minus
打包时,Tree-Shaking 会识别到 minus 未被使用,最终输出的代码中会剔除 minus 的定义,只保留 add 相关逻辑。
实际应用中的注意事项
工具配置:
Webpack 需在
mode: 'production'下自动启用 Tree-Shaking(开发环境默认不开启,避免影响构建速度)。Rollup/Vite 天生对 ESM 支持更好,Tree-Shaking 优化更彻底。
避免副作用代码:
如果模块中存在“副作用”(如直接执行的代码、修改全局变量等),工具可能无法安全剔除该模块,需通过/*#__PURE__*/注释标记纯函数,告诉工具“此代码无副作用,可安全删除”。示例:
// 有副作用(无法被剔除) console.log('这行代码会执行'); // 无副作用(可被 Tree-Shaking 剔除,若未被使用) /*#__PURE__*/ (() => { console.log('这行代码仅在函数被调用时执行'); })();第三方库的处理:
部分第三方库可能仍使用 CJS 格式,或包含大量副作用代码,导致 Tree-Shaking 无法生效。此时可选择 ESM 格式的库(如通过package.json的module字段指定 ESM 入口)。
总结
Tree-Shaking 是基于 ESM 静态分析的代码优化技术,通过剔除未使用的代码显著减小打包体积,是现代前端工程化中提升性能的重要手段。其效果依赖于 ESM 的正确使用和工具的合理配置。