tree shaking 通过静态分析 es module 的 import/export 关系剔除未引用的导出,前提是第三方库提供 esm 入口、按需导入(如 lodash-es/debounce)、避免副作用代码,并配置构建工具启用摇树优化。

Tree Shaking 本身不直接剔除“第三方库”,而是剔除未被引用的模块导出(exports),前提是这些库支持 ES Module(ESM)语法且构建工具(如 Webpack、Vite、Rollup)能静态分析 import/export 关系。真正要减少冗余的第三方代码,关键在于:让库以 ESM 形式引入 + 确保只导入实际用到的部分 + 避免破坏摇树的写法。
确保第三方库提供 ESM 入口并被正确解析
很多 npm 包同时提供 CommonJS(cjs)和 ESM(mjs 或 package.json 中的 "module" / "exports" 字段)。如果构建工具加载了 cjs 版本,就无法进行 Tree Shaking,因为 require 是运行时动态的,无法静态分析。
- 检查库的 package.json:确认有 "module"(指向 ESM 入口)或符合规范的 "exports" 字段(例如
"exports": { ".": { "import": "./dist/index.mjs" } }) - 在 Webpack 中可通过 resolve.mainFields 强制优先使用 ESM:
["browser", "module", "main"] - Vite 和 Rollup 默认优先处理 ESM,但仍建议确认库发布的包结构(如 lodash-es 而非 lodash)
按需导入,避免默认全量引入
即使库支持 ESM,若写 import _ from 'lodash',仍可能引入整个包(尤其当它没有精细的 ESM 拆分时)。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 优先使用官方提供的 ESM 分发版本,例如:
import debounce from 'lodash-es/debounce';(lodash-es 是专为 Tree Shaking 优化的版本) - 对支持子路径导出(subpath exports)的库,用精确路径:
import { parseISO } from 'date-fns';✅(date-fns v2+ 已 ESM 化,可摇)import dateFns from 'date-fns';❌(会引入全部) - 避免
import * as xxx(除非确定所有成员都被用到),它可能阻碍导出识别
警惕破坏 Tree Shaking 的常见写法
即使用了 ESM,某些代码模式会让打包器保守地保留模块,认为它有副作用。
- 禁止在模块顶层写无副作用的“执行语句”(如 console.log、函数调用、new 实例)——这会让整个模块被标记为 有副作用,无法被移除
- 避免给 export default 赋值一个立即执行函数或复杂对象字面量(Webpack 可能无法判定其是否可安全剔除)
- 不要在
import后立刻调用方法(如import { init } from './utils'; init();),应确保调用逻辑可被静态判定为“未使用” - 确认构建配置中 mode: 'production' 且 optimization.usedExports: true(Webpack)或启用 treeShaking: true(Rollup/Vite 默认开启)
辅助验证与调试方法
光写对还不行,得确认它真的被摇掉了。
- Webpack:加
--stats-chunks或用 webpack-bundle-analyzer 查看模块依赖图,定位未被引用却残留的大体积模块 - Vite:运行
vite build --report生成report.html,观察哪些第三方模块占比较高但实际使用极少 - 查看最终打包产物源码(如 dist/assets/*.js),搜索未使用的函数名是否存在;也可启用
optimization.concatenateModules: false(Webpack)避免模块合并,便于追踪原始模块 - 用
import { something } from 'xxx'后故意不使用something,再构建,看是否真的消失 —— 这是快速验证是否生效的实操方式
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










