我们在日常开发的时候会引入非常多的模块文件,每个模块文件可能会有很多的方法逻辑,但有些方法我们并不能保证一定能用到,比如:
export const add = (a, b) => {
console.log(a + b)
}
export const minus = (a, b) => {
console.log(a - b)
}
import { add } from './math';
add(1, 2)
在上面文件中,math.js
文件暴露出两个方法,index.js
文件只引入math.js
文件中的add
方法。
当我们运行npm run build
进行打包的时候,查看产出文件夹dist
下面的main.js
文件后发现,math.js
里面的minus
文件方法也被打包了出来,这很显然是没有必要的。
最理想的打包方式是我引入了什么,你就给我打包什么,这样就把没用到的方法进行了移除,减少文件的大小。webpack2.0+
已经支持Tree Shaking
这个概念,它的作用实际上就是把一个模块没用的东西都摇晃掉。
拿上面的代码举例,我src/index.js
文件只引入了add
方法,你只给我打包add
方法就好了,这就是Tree Shaking
的作用。
:::warning
⚠️ 注意
另外它只支持ESModule
的模块化,不支持CommonJS
的模块导入。
这是因为ESModule
引入文件的时候是静态引入的,编译时引入(代码还没运行就要知道引入了哪些资源)
而CommonJS
是动态引入,执行时引入,是可以根据逻辑决定是否要引入的,这就对Webpack
来说有点困难了。
:::
现在我们的配置文件是development
开发模式,而development
实际上是没有开启Tree Shaking
的。
对webpack.config.js
进行配置:
module.exports = {
mode: "development",
devtool: "eval-cheap-module-source-map",
// ...
optimization: {
// 当 src/index.js 文件使用了导出的函数时,这个函数才会被打包
usedExports: true
}
}
对package.json
进行设置:
{
"name": "chapter01",
// sideEffects: false 表示对所有的文件都进行 Tree Shaking 分析
"sideEffects": false,
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"dev": "webpack serve",
"build": "webpack"
},
"author": "",
"license": "ISC",
"devDependencies": {
// ...
},
"dependencies": {
// ...
}
}
sideEffects
用来设置对一些文件不使用Tree Shaking
,例如我们要使用的@babel/ployfile
:
import "@babel/ployfile";
import "./index.css"
像这样直接导入整个文件,而不是导入导出某个功能的时候就需要我们进行排除,让Tree Shaking
不进行分析,否则Tree Shaking
会认为src/index.js
没有使用任何的导出功能!!!
{
// ...
"sideEffects": ["*.css", "@babel/ployfile"]
// ...
}
而**pakcage.json**
中的**sideEffects: false**
表示对所有文件都进行**Tree Shaking**
。
配置了以上的两个文件之后再进行打包:
从代码中可以看出math.js
文件提供了两个方法,但是只使用了一个。虽然现在minus
方法依然被打包出来,但是现在webpack
知道只有add
方法被使用了。
:::warning
⚠️ 注意
在development
的模式下即使你开启了Tree Shaking
,minus
方法也不会被移除掉,这是因为方便我们使用source-map
进行调试,当使用production
的模式打包时Tree Shaking
才会真正的生效,而production
模式其实默认配置了Tree Shaking
。
:::
使用production
模式进行打包:
{
// ...
"sideEffects": false
// ...
}
module.exports = {
mode: "production",
devtool: "cheap-module-source-map", // 需要设置为 cheap-module-source-map
// 使用了导出内容的话就进行导出
optimization: {
usedExports: true,
},
// ...
};
这个时候进行打包就会把无用的功能进行了移除(摇晃掉)。