文章目录
- 一文大白话讲清楚webpack基本使用——17——Tree Shaking
- 1. 建议按文章顺序从头看,一看到底,豁然开朗
- 2. 啥叫Tree Shaking
- 3. 什么是死代码,怎么来的
- 3. Tree Shaking的流程
- 3.1 标记
- 3.2 利用Terser摇起来
- 4. 具体使用方式
- 4.1 适用前提
- 4.2 使用流程
- 5. 副作用代码
- 5.1 通过webpack.config.js中sideEffects指定
- 5.2 通过package.json中sideEffects配置
一文大白话讲清楚webpack基本使用——17——Tree Shaking
1. 建议按文章顺序从头看,一看到底,豁然开朗
- 第一篇:
- 一文大白话讲清楚啥是个webpack
- 第二篇:
- 一文大白话讲清楚webpack基本使用——1——完成webpack的初步构建
- 第三篇
- 一文大白话讲清楚webpack基本使用——2——css相关loader的配置和使用
- 第四篇
- 一文大白话讲清楚webpack基本使用——3——图像相关loader的配置和使用
- 第五篇
- 一文大白话讲清楚webpack基本使用——4——vue-loader的配置和使用
- 第六篇
- 一文大白话讲清楚webpack基本使用——5——babel的配置和使用
- 第七篇
- 一文大白话讲清楚webpack基本使用——6——热更新及其原理
- 第八篇
- 一文大白话讲清楚webpack基本使用——7——代码分离和懒加载
- 第九篇
- # 一文大白话讲清楚webpack基本使用——8——开发环境和生产环境的配置和区别
- 第十篇
- 一文大白话讲清楚webpack基本使用——9——预加载之prefetch和preload以及webpackChunkName的使用
- 第十一篇
- 一文大白话讲清楚webpack基本使用——10——使用CDN优化加载速度
- 第十二篇
- 一文大白话讲清楚webpack基本使用——11——chunkIds和runtimeChunk
- 第十三篇
- 一文大白话讲清楚webpack基本使用——12——文件指纹和缓存机制
- 第十四篇
- 一文大白话讲清楚webpack基本使用——13——Js代码压缩
- 第十五篇
- 一文大白话讲清楚webpack基本使用——14——CSS代码压缩
- 第十六篇
- 一文大白话讲清楚webpack基本使用——15——HTML代码压缩
- 第十七篇
- 一文大白话讲清楚webpack基本使用——16——图片压缩
- 然后看本篇,Tree Shaking
2. 啥叫Tree Shaking
- Tree,就是树,Shaking就是摇,摇树,为啥要摇树,让我们想起一件事
- 果农秋收的时候,发现树上的果实有点已经烂了,有的还新鲜着,果农就想,我把这个树上不好的果子都去掉,怎么去呢,大力摇树,因为坏了的果子根部不牢固了,稍微用力摇就能掉下来。
- 经过一番摇动之后,剩下的果实就是我们需要的好果实了。
- 这就是Tree Shaking。
- 回到webpack中,Tree Shaking就是在构建的时候把无用的代码(死代码)去掉,只保留有用的代码,这样就能缩减构建包的体积
3. 什么是死代码,怎么来的
- 啥是死代码,就是在程序运行的生命周期内(webpack认为的,不是全部的)始终不被执行的代码
- 为啥始终得不到执行呢,这是因为在ES6模块出,我们通过export暴露外部接口,如果有些程序体既没有被暴露出去,内部有没有引用依赖,那么他讲永远无法被调用执行,这时,他就成了死代码
- 比如我们在一个js文件里面写了两个方法,一个add,一个reduce
function add(x,y){
return x+y
}
function reduce(x,y){
return x-y
}
export{
add
}
- 我们通过export之暴露了add,没有暴露reduce,那么reduce将无法被执行,就成了死代码
- 或者我们通过import导入了add 和reduce,但是只用了add,没用reduce,也是一样的
import {add ,reduce} from 'xxx'
add()
// recuce()//一直未使用,也是死代码
- 可是,问题来了,为什么我们说这仅是webpack认为的死代码
- 因为者设计一个概念,我们举个例子,你给我钱了,我没要;和你给我钱了,我没花;这两个最终的结果都是我没花你的钱,但是后者需要我用完钱了,我才能知道你到底花没花你的钱。而前者不一样,我一开始就知道我没花,因为我压根就没要你钱。
- 放在程序里面,正常情况下,只有程序运行完了,我们才知道哪些代码没有被执行。之所以能提前知道有些代码不能被执行,是因为程序压根就没引入这些代码。为啥能知道呢,就是因为ES6模块没有暴露这个接口,这个事情,我们在编译的时候就能知道,不用等到运行时。
- 这也是为什么webpack在构建时就可以识别出来有用和无用的代码
3. Tree Shaking的流程
3.1 标记
- webpack会从入口文件出发,递归的分析代码中的模块依赖,标记处用到的模块和导出的函数和变量
- 具体标记如下:
- 所有import标记为/* harmony import*/
- 所有用到的export标记为/* harmony export([type]) */其中type和webpack内部有关,可能值为binding,immutable等
- 没被使用过的import标记为/* unused harmony export [FunctionName] */ 其中FunctionName为export的方法名称
3.2 利用Terser摇起来
- 通过Terser删除掉没有被用到的到导出语句
4. 具体使用方式
4.1 适用前提
- 前面讲过了,Tree Shaking的适用前提是我们通过ES6模块实现接口暴露,而不能是CommonJS(我们之前就是这么写的,不要改)
- 另外就是一般在production环境下,默认开启Tree Shaking
- 配置optimization.usedExports:true
- 最后,要配置JS代码压缩,因为Tree Shaking发生在代码压缩阶段(我们之前讲JS代码压缩,已经配置过了,不要改)
4.2 使用流程
-
首先,我们修改mode为production
-
然后配置optimization.usedExports:true
-
为了验证TreeShaking是否生效,我们在src/modulejs/add.js里面新增一个addThird方法,函数体长一些,暴露
-
然后我们在main.js里面倒入addTHird,并使用
-
构建打包
npm run build
-
看构建后bundle体积
91KB -
然后在main.js里面注销addTRhird的调用
-
可以看到在编辑器里面倒入的时候addTRhird变量变灰了,说明未使用
-
然后重新构建打包
npm run build
- 看看体积
90KB了,说明addTRhird没有被打包进来 - 有人会问了,为啥不在打包的js里面查看一下是否打包了addTRhird方法,因为我们把代码压缩了,找起来比较麻烦,谢谢
- ok ,摇完了
5. 副作用代码
- 简单点,啥叫副作用,就是函数除了返回值还干了点别的
let a=0;
function add (x,y){
a=2;
return x+y
}
add(1,2)
- add除了返回x+y,还修改了外部变量,所以他是副作用函数
- 为啥要讲副作用,就是有些代码没用但是又不想删除
- 明白没有,就是比如这个add函数可能我们最后在main.js没引用,构建的时候本该删除,但是删了他影响了a,所以我们要考虑一下要不要删
- 如果不想删,我们可以指定配置,有副作用的代码的不删除
5.1 通过webpack.config.js中sideEffects指定
- 在webpack.config.js里面配置sideEffects数组,数组元素是具有副作用的模块js
module.exports={
sideEffects:['./xxx.js']
}
5.2 通过package.json中sideEffects配置
{
sideEffects:true//所有导入文件都视为有副作用
sideEfeects:false//都没有副作用
sideEffects:['sss/jx']//指定哪些有副作用
}