1. 核心回答(一句话)
Tree Shaking 就是在打包过程中,把没用到的代码排除掉,最终不放进 bundle。
2. 第一层:它到底怎么做到的?
如果面试官追问"怎么排除的",再说:
打包器会先
分析模块之间的依赖和代码的使用情况,标记没用到的代码,最后生成 bundle 时把它排除掉。
流程:
text
源码
↓
解析模块
↓
分析依赖和使用关系
↓
标记没用代码
↓
生成 bundle
↓
无用代码不进入最终产物
3. 第二层:为什么 ES Module 特别适合 Tree Shaking?
面试官继续问:
因为 ES Module 的
import/export是静态的,打包阶段就能知道模块之间怎么依赖、哪些导出被使用。
例如:
javascript
// utils.js
export function add(a, b) {
return a + b;
}
export function minus(a, b) {
return a - b;
}
javascript
import { add } from './utils.js';
add(1, 2);
打包器可以分析出:
text
utils.js
├── add → 使用了
└── minus → 没使用
于是 minus 就具备被 Tree Shaking 掉的条件。
4. 第三层:为什么 CommonJS 不容易做?
因为 CommonJS 更动态,
require()在运行时决定加载什么,构建阶段不一定能准确知道哪些代码会被使用。
例如:
javascript
const name = getModuleName();
const module = require(name);
构建阶段很难确定:
text
name 到底是什么?
↓
到底 require 哪个模块?
↓
到底会用到哪个导出?
所以更准确的说法不是:
CommonJS 的动态特性让静态分析和安全删除变得困难,因此不像 ES Module 那么适合 Tree Shaking。
5. 第四层:sideEffects 是干什么的?
这是 Tree Shaking 的另一个高频追问。
sideEffects是告诉打包工具:哪些模块有副作用,不能随便删。
对,这一层也应该严格遵守**"先给面试者一句能直接说的话,再展开"**,而不是上来讲一堆。
5. 第四层:sideEffects 是干什么的?
核心回答(一句话)
sideEffects是告诉打包工具:哪些模块有副作用,不能随便删。
为什么需要它?
比如:
javascript
// style.js
console.log('初始化');
export const name = '张三';
即使:
javascript
import { name } from './style.js';
name 没有被使用,也不能直接把整个模块删掉。因为:
javascript
console.log('初始化');
执行本身就会产生影响。
所以 Tree Shaking 实际要判断两件事
text
代码有没有被使用?
↓
没使用
↓
有没有副作用?
↙ ↘
有 没有
↓ ↓
不能随便删 可以删
sideEffects: false
json
{
"sideEffects": false
}
意思可以简单理解成:
告诉打包工具:
这个包里的模块默认没有副作用,可以放心做更激进的 Tree Shaking。
所以这一层真正要记住的就一句:
Tree Shaking 不只是判断"有没有使用",还要判断"删掉会不会产生影响";
sideEffects就是帮助打包工具判断这个问题的。
6. Tree Shaking 和代码压缩的区别
这是另一个很容易混淆的点。
text
Tree Shaking
→ 判断哪些代码没必要保留
代码压缩
→ 对保留下来的代码继续优化
例如:
javascript
function add(a, b) {
return a + b;
}
压缩器可能把它进一步压缩成更短的形式。所以:
Tree Shaking 解决的是"代码留不留",代码压缩解决的是"留下以后怎么变得更小"。
7. 最后形成一条完整追问链
面试官可能这样一路问:
text
Tree Shaking 是什么?
↓
为什么能把代码排除掉?
↓
怎么判断哪些代码没用?
↓
为什么 ES Module 可以静态分析?
↓
为什么 CommonJS 不容易做?
↓
如果代码有副作用怎么办?
↓
sideEffects 是干什么的?
↓
Tree Shaking 和代码压缩有什么区别?
最终满分回答
如果面试官只给你一次机会,让你完整回答:
Tree Shaking 就是在打包过程中,把没用到的代码排除掉,最终不放进 bundle。
它主要依赖 ES Module 的静态
import/export,打包阶段就能分析出哪些代码被使用、哪些没被使用。不过没使用不代表一定能删,还要判断代码有没有副作用。