作用
Tree-shaking是webpack内置的一个优化,主要功能就是去除没有用到代码。因为JavaScript大多数是要通过加载的,加载的文件越小,性能越好,所以Tree-shaking对于优化JavaScript很有意义。
这部分代码也被称为Dead Code
Dead Code 一般具有以下几个特征
• 代码不会被执行,不可到达
• 代码执行的结果不会被用到
• 代码只会影响死变量(只写不读)
原理
Tree-shaking主要依赖于ES6的模块化import和export,我们都知道ES6的module只能是顶层出现,和运行时无关,不能运行时加载,Tree-shaking主要就是依靠这个基础进行静态分析,不执行代码就从字面量对代码进行分析。如果是require,需要执行后才知道有没有引用,就无法进行Tree-shaking。
ES6 module 特点:
- 只能作为模块顶层的语句出现
- import 的模块名只能是字符串常量
- import binding 是 immutable的
ES6模块依赖关系是确定的,和运行时的状态无关,可以进行可靠的静态分析,这就是tree-shaking的基础。
所谓静态分析就是不执行代码,从字面量上对代码进行分析,ES6之前的模块化,比如我们可以动态require一个模块,只有执行后才知道引用的什么模块,这个就不能通过静态分析去做优化。
例子
// app.js
export function A(a, b) {
return a + b
}
export function B(a, b) {
return a + b
}
// index.js
import {A,B } from '/app.js'
当index.js 调用了A函数 那么bundle只会打包A函数,如果两个都不调用 那么bundle都不会打包。
Tree-shaking副作用
如果在app.js 调用A函数,index.js只用引入没用调用函数A,那么bundle也会打包A函数,这就是Tree-shaking带来的副作用。
webpack4开始,在pacakge.json里面添加一个配置:
"sideEffects": false
sideEffects主要是让 webpack 去除 tree shaking 带来副作用的代码。不管有没有副作用,只要没有被引用,都会被清除。但是会引申出另一个问题,如果配置了,那么很多简单引用都会被忽略,比如引入一个css。所以为什么那么多脚手架都不会去配置这个参数,并不能保证开发者能保证代码都没有副作用。
当然,webpack还给了配置参数,sideEffects可以是一个数组,指定文件没有副作用,不需要去过滤没有使用的副作用。话说回来,除非项目真的很严格,不然不建议配置,否则开发的时候没问题,打包之后出问题了,不知道这个配置的很可能会心态爆炸,定位不到问题。
Teee-shaking还有对于类的作用也会有问题,当我们没有引入babel的时候,遵循函数的方式进行shaking,但是引入babel之后,转化成ES5,就会产生副作用,从而没办法达到想要的结果。
webpack mode设置为production 会自动开启Tree-Shaking
网友评论