treeShaking原理
本文最后更新于103 天前,其中的信息可能已经过时,如有错误请发送邮件到1986413837@qq.com

1.核心前提 : ES6 Module

Tree Shaking 生效的根本前提是代码必须使用 ES6 模块语法(import / export,而不是 CommonJS(require / module.exports

CommonJS 是动态的: 模块的导入和导出可以在代码运行时发生变化(例如放在 if 语句中)。构建工具在编译时无法确定到底引用了什么。

ES6 Module 是静态的: importexport 必须在顶层,不能在条件语句中。这意味着构建工具可以通过静态分析(即不运行代码,只分析代码结构)就能确定模块之间的依赖关系。

2.工作流程(三步走)

第一步:静态分析 (AST 解析)

构建工具(如 Webpack)在构建过程中,会把源码解析成 AST(Abstract Syntax Tree)。通过分析 AST,它能清楚地知道:

  • 哪个文件导出了(export)哪些变量/函数。
  • 哪个文件导入了(import)哪些变量/函数。

第二步:标记 (Marking)

构建工具会从入口文件(Entry)开始遍历,标记所有被使用的模块导出。

  • 如果一个模块导出了函数 A 和函数 B,但在其他文件中只 import { A },那么函数 A 被标记为“使用中”。
  • 函数 B 虽然被导出了,但没有被引用,因此不会被标记。

第三步:消除 (Elimination)

这一步通常由代码压缩工具(Minifier,如 TerserUglifyJS)完成。 当压缩工具处理代码时,它会识别出那些被标记为“未引用”的代码(Dead Code),直接将其从最终的 Bundle 中剔除。

3.代码示例

//utils.js
export function add(a, b) {
  return a + b;
}

export function minus(a, b) { // 这个函数没有被用到
  return a - b;
}
//main.js
import { add } from './utils';

console.log(add(1, 2));

Tree Shaking 后的结果: minus 函数会被完全丢弃,最终打包结果里只有 add 函数和 console.log

4.最大障碍 : 副作用(Side Effects)

这是 Tree Shaking 中最容易踩坑的地方。

什么是副作用? 副作用是指一个模块除了导出成员之外,还做了其他事情,例如:

  • 修改全局变量(如 window.polyfill = ...)。
  • 在原型链上添加方法(如 Array.prototype.includes = ...)。
  • 引入 CSS 文件(import './style.css')。
  • 执行 console.log

为什么副作用会阻碍 Tree Shaking? 如果构建工具发现一个文件有“副作用”,即使你没有在代码里显式引用它的导出内容,构建工具也不敢轻易删除它,因为它担心删除后会破坏程序的逻辑。

5.总结

依赖 ESM: 利用 ES6 模块的静态特性。

构建依赖图: 遍历代码,分析 import/export。

可达性分析: 判断哪些导出的代码被使用了,哪些是“死代码”。

压缩删除: 结合 Terser 等压缩工具,将未使用的代码物理移除。

副作用处理: 通过 sideEffects 标记,手动告知工具哪些文件可以安全跳过副作用检查。

Life's a struggle, I'll conquer it.
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇