乐趣区

webpacktree-shaking

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.jsfunction 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 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

开头讲过,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))


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

友情提示:

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

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

退出移动版