webpack4-(1)-Tree Shaking

168 阅读2分钟

Tree Shaking

什么是Tree-Shaking    

tree shaking 是一个术语,通常用于描述移除 JavaScript 上下文中的未引用代码(dead-code)。它依赖于 ES2015 模块系统中的静态结构特性,例如 import 和 exporttreeshaking.gif

webpack在 mode=development 时,默认是不会开启tree-shaking的。需要在 webpack.config.js 中配置

...
optimization: {
	 usedExports: true
}
...

配置完以前设置之后,再模拟一个实际使用的场景。
首先,先创建一个js文件 utils.js 

utils.js 

export const add = (a, b) =>{ 
    return a + b
}

export const minus = (a, b) => {
    return a - b
}

然后在 main.js 中引入并使用。

main.js 

import {add, minus} from './utils'

console.log(add(1,2))
if(false){
    // 达不到的代码不会被打包
    console.log(minus(4,2))
}

执行 npx webpack 打包后查看打包结果
WX20200921-230404@2x.png
可以看到, utils.js 中两个模块都被引入,但是被使用的只有 add 方法。minus 方法没有没用到,所以在打包的时候被剔除了。
development 环境中为了方便调试,只会把模块的使用状态标识一下,并不会真正的把其他未使用的模块剔除。

上面说到过tree-shaking对 ES Module生效,而对CommonJs不生效,接下来我们做个试验。
首先,我们创建一个js文件 utils2.js 。
utils2.js 

const add2 = (a, b) =>{
    return a + b
}
const minus = (a, b) =>{
    return a - b
}
module.exports = {
    add2,
    minus
}

然后在 main.js 中引入并使用。

/***************CommonJs引入************/
const count = require('./utils2')
console.log(count.add2(5,6))

然后执行打包命令,查看结果。
image.png
可以看到,“没有找到静态导出,所以的导出都被使用”
所以证实了上面所说的 tree-shaking依赖于 ES2015 模块系统中的静态结构特性。

Tree-Shaking的副作用

在我们的开发中,不仅仅会有上面使用引入模块的方式,还经常会有下面的引入方式:

import './common.css'
...
...

上面的这种引入方式,因为整个文件引入,所以这个文件不管你是否使用都被被打包,为了避免过多的无用模块被打包,所以我们可以在 package.json 中配置 "sideEffects":false 来消除副作用,这样这种引入方式的引入的模块就不会被打包。
但是这样设置以后又会带来其他问题。比如说,在common.css 中我们设置 body 的背景色为蓝色。然后在 production 环境下进行打包,会发现 body 设置的样式并没有生效。
我们可以通过设置sideEffects 的配置项来对这种情况进行修正。
sideEffects可接受一个数组,我么设置为

...
"sideEffects": ["*.css"]
...

我们再进行打包,这时候我们设置的样式就生效了。

总结

我们在项目中使用tree-shaking需要注意以下几点。

  • 使用 ES2015 模块语法(即 importexport)。
  • 在项目 package.json 文件中,添加一个 "sideEffects" 入口。