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/
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。