1、什么是 tree shaking?
所谓 Tree-shaking
就是‘摇’的意思,作用是把项目中没必要的模块全部抖掉,用于在不同的模块之间消除无用的代码,可列为性能优化的范畴。
举个例子:
目录结构:
在 util.js
中编写如下代码:
// util.js
export function a() {return 'this is function"a"'}
export function b() {return 'this is function"b"'}
export function c() {return 'this is function"c"'}
在 app.js
中引用 util.js
的 function a()
函数,按需引入:
// app.js
import {a} from './util'
console.log(a())
运行 cnpm run build
打包,注意 :tree shaking
只能在生产环境下生效
如果将查找内容换成 this is function "c"
或者 this is function "b"
, 并没有相关查找结果。说明 JS Tree Shaking
成功。
2、tree shaking 原理
Tree-shaking
的本质用于消除项目一些不必要的代码。早在编译原理中就有提到DCE(dead code eliminnation)
,作用是消除不可能执行的代码,它的工作是使用编辑器判断出某些代码是不可能执行的,然后清除。
Tree-shaking
同样的也是消除项目中不必要的代码,但是和 DCE
又有略不相同。可以说是 DCE
的一种实现,它的主要工作是应用于模块间,在打包过程中抽出有用的部分,用于完成DCE
。
Tree-shaking
是依赖 ES6
模块静态分析的,ES6 module
的特点如下:
- 只能作为模块顶层的语句出现
-
import
的模块名只能是字符串常量 -
import binding
是immutable
的
依赖关系确定,与运行时无关,静态分析。正式因为 ES6 module
的这些特点,才让 Tree-shaking
更加流行。
主要特点还是依赖于 ES6
的静态分析,在编译时确定模块。如果是require
,在运行时确定模块,那么将无法去分析模块是否可用,只有在编译时分析,才不会影响运行时的状态。
3、如何处理第三方 js 库?
下面以 lodash.js
库为例进行介绍
首先安装lodash.js
cnpm install lodash --save-dev
在 app.js
里引入使用
// app.js
import {chunk} from 'lodash'
console.log(chunk([1, 2, 3], 2))
运行 cnpm run build
打包,发现打包后的文件竟然还有 70.9kb
,我仅仅用了lodash
中的一个函数,这明显没有tree shaking
开头讲过,js tree shaking
利用的是 ES
的模块系统。而 lodash.js
使用的是 CommonJS 而不是 ES6 的写法。所以,安装对应的模块系统即可。
安装 lodash.js
的 ES
写法的版本:npm install lodash-es --save
修改一下 app.js
:
// app.js
import {chunk} from 'lodash-es'
console.log(chunk(['1', '2', '3'], 2))
再次打包,打包结果只有 3.42KB
(如下图所示)。显然,tree shaking
成功。
友情提示:
在一些对加载速度敏感的项目中使用第三方库,请注意库的写法是否符合
ES
模板系统规范,以方便webpack
进行tree shaking
。
还有一点,tree shaking
只在生产模式下有用
参考:
https://juejin.im/post/5c6618275188256261128d8d
https://itxiaohao.github.io/passages/webpack4-tree-shaking/