删除|Webpack | TreeShaking工作原理

删除|Webpack | TreeShaking工作原理

文章图片

【删除|Webpack | TreeShaking工作原理】删除|Webpack | TreeShaking工作原理

文章图片

删除|Webpack | TreeShaking工作原理

文章图片

删除|Webpack | TreeShaking工作原理


阅读本文约8分钟
阅读本文 , 你将了解
1. Tree Shaking 的工作流程
2. 实现 Tree Shaking 的前提
3. Tree Shaking 的副作用
目的
本质上为了消除无用的js代码 , 减少加载文件体积的方式 , 使其整体执行时间更短 。

那么如何判断js代码的“无用”?
这些无用的代码 , 又有另外一种叫法:Dead Code 。
而Dead Code是被怎么定义的:

实现前提
1. Tree Shaking 的执行环境宿主一般是Node , 而不是浏览器
2. 若JavaScript 是模块化的 , 那么必须遵循 ES6 Module 规范 , 而不是 CommonJS 或其他 , 主要是因为 ES6 Module 可以静态分析的 。 ”
“前者通过作用域分析 , 分析出代码里变量所属的作用域以及他们之间的引用关系 , 进而可以推导出变量和导入依赖变量的引用关系 。 ”

3. 将mode 选项为  \"production\" , 以启用tree shaking和minification(代码压缩) 。
4. 确保没有把compiler将 es6 模块语法转换为CommonJS模块 。 这一块很重要 , 在你使用babel-loader或者ts-loader编译代码时 , 一定要保留  import 和 export 。
原理
首先 ,Tree-Shaking 实现分两步走 ,
Step 1:标记出模块 导出值哪些没有被用过
Step 2:使用 Terser 删除掉没有被用到的导出语句
其中 , 标记过程又可以分为三个步骤:
Make阶段 ,  收集导出变量并记录到模块依赖图ModuleGraph 变量中 。
Seal阶段 , 遍历ModuleGraph 标记模块导出变量有 没有被使用
生成产物时 , 若变量没有被其他模块使用时则 删除对应的导出语句
标记功能需要配置 optimization.useExports = true  开启
标记效果
webpack负责对代码进行标记 , 把 import & export 标记为3类:
1. 所有 import 标记为  /* harmony import  */ ,
被使用过的 export 标记为 /* harmony export([type
)*/ , 其中 type 和 webpack 内部相关 , 可能是 binding , immutable 等等 。
2. 没被使用过的 import 标记为 /* unused harmony export [FuncName
*/ , 其中 FuncName 为 export 的方法名称
实例说明

「注:省略了 bundle.js 上边 webpack 自定义的模块加载代码 , 那些都是固定的 。 」
由上可得:

bye 没有被使用 , 被标记为
/* unused harmony export bye*/
hello 被使用为正常的
/*harmony export(imutable) */
删除
使用 Terser 就可以进行第二步 , 把 bye 彻底清除

副作用
副作用是函数式编程的一个概念 , 是指当调用函数时 , 除了返回函数值之外 , 还会对调用函数产生附加的影响 。
简单来说 , 就是除了返回值以外 , 还做了其他事情 。
比如
- 打印Log ,
- 读取和修改外部变量等 。
- 导入css文件 , 引入Polyfill 等 。
副作用代码不可被删除
举个例子:

以上可知 , 虽然a变量没有被其他地方使用 , 但由于副作用 , 如果将其删除 。