1、什么是tree shaking?

所谓Tree-shaking就是‘摇’的意思,作用是把项目中没必要的模块全部抖掉,用于在不同的模块之间消除无用的代码,可列为性能优化的范畴。

举个例子:
目录结构:
2.png
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.jsfunction a() 函数,按需引入:

// app.js
import { a } from './util'
console.log(a())

运行cnpm run build打包,注意tree shaking只能在生产环境下生效
3.png
如果将查找内容换成 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 bindingimmutable

依赖关系确定,与运行时无关,静态分析。正式因为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
4.png

开头讲过,js tree shaking 利用的是 ES 的模块系统。而 lodash.js 使用的是CommonJS而不是ES6的写法。所以,安装对应的模块系统即可。

安装 lodash.jsES 写法的版本:npm install lodash-es --save

修改一下 app.js:

// app.js
import { chunk } from 'lodash-es'

console.log(chunk(['1', '2', '3'], 2))

5.png
再次打包,打包结果只有 3.42KB(如下图所示)。显然,tree shaking 成功。

友情提示:

在一些对加载速度敏感的项目中使用第三方库,请注意库的写法是否符合 ES 模板系统规范,以方便 webpack 进行 tree shaking
还有一点, tree shaking只在生产模式下有用

参考:
https://juejin.im/post/5c6618275188256261128d8d
https://itxiaohao.github.io/passages/webpack4-tree-shaking/


记得要微笑
1.9k 声望4.5k 粉丝

知不足而奋进,望远山而前行,卯足劲,不减热爱。


引用和评论

0 条评论