一、tree-shaking是什么?
这个词应该咱们都不陌生了,翻译过来便是“树摇”。
看一下官方的解释:
Tree shaking is a term commonly used in the JavaScript context for dead-code elimination. It relies on the static structure of ES2015 module syntax, i.e.
import
andexport
. The name and concept have been popularized by the ES2015 module bundler rollup.
简言之,tree-shaking
有助于咱们减少打包后产物的体积,去掉无用的代码。这儿不多说概念,本文的重点还是在于文章标题,咱们重视的是webpack
的tree-shaking
能力以及触发条件。
二、建立Webpack环境
创立项目
mkdir tree-shaking-webpack && cd tree-shaking-webpack
运用pnpm
初始化package.json
pnpm init
装置webpack
和webpack-cli
pnpm add webapack webpack-cli -D
创立webpack.config.js
装备文件
// webpack.config.js
const path = require("path");
module.exports = {
entry: "./src/main.js",
output: {
path: path.resolve(__dirname, "./dist"),
filename: "bundle.js",
},
};
修正package.json
{
"name": "tree-shaking-webpack",
"version": "1.0.0",
"description": "",
"main": "./src/main.js", // 修正进口
"scripts": {
"build": "webpack --config ./webpack.config.js" // 添加build指令
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"webpack": "^5.89.0",
"webpack-cli": "^5.1.4"
}
}
创立进口文件
// src/main.js
console.log('hello wolrd')
履行build
指令,能够看到现已打包成功了
但是控制台报了个正告,原因是没有装备mode
,咱们装备mode
为开发形式development
即可
// webpack.config.js
const path = require("path");
module.exports = {
mode: "development", //开发形式
entry: "./src/main.js",
output: {
path: path.resolve(__dirname, "./dist"),
filename: "bundle.js",
},
};
再次履行build
,控制台不再报错
三、webpack的tree-shaking
1、经过ES6的import和export触发
依据前面tree-shaking
介绍中提到,tree-shaking
其实依赖了ES6
中的import
和export
。
所以假如咱们先做第一个测验:commonJS
是否支撑tree-shaking
咱们新增个compute.js
文件
// src/compute.js
const add = (a, b) => {
return a + b;
};
const sub = (a, b) => {
return a - b;
};
module.exports = {
add,
sub,
};
main.js
中引证compute.js
,而且只运用add
办法
const { add, sub } = require("./compute");
console.log(add(1, 2));
履行打包后,发现main.js
中sub
办法也被打打包了
咱们换成ES6
标准的导入和导出
// src/compute.js
export default {
add,
sub
}
// src/main.js
import { add, sub } from './compute.js'
履行打包,main.js
中不再呈现sub
办法
所以得出结论,假如要触发tree-shaking
,需求经过ES6
的import
和export
触发。
2、经过解构的办法触发
在满意第一点的条件下,咱们试想一下,假如咱们是import
整个目标,是否会触发tree-shaking
呢?例如:
import compute from './compute'
console.log(compute.add(1,2))
由于这个事例的打包文件体积比较小,咱们看不太出来,咱们测验装置一个lodash
来试一下,需求注意的是,咱们需求装置的是lodash
的ESM
版别,即lodash-es
,不然官方默认的lodash
是commonJS
标准
pnpm add lodash-es
修正main.js
的内容
// src/main.js
import { get } from "lodash-es";
console.log(get({ a: 1 }, "a"));
履行打包,并创立index.html
文件引进打包后的bundle.js
打开index.html
,检查bundle.js
的体积巨细为103kb
假如咱们不运用解构的办法,直接引进整个lodash
,然后打包
// src/main.js
import _ from "lodash-es";
console.log(_.get({ a: 1 }, "a"));
再次打包后,能够看到,bundle.js
的体积巨细现已来到了恐惧的1.6MB
经过tree-shaking
之后,bundle.js
只打包了lodash
的get
办法,其他无关的办法都被“摇走了”
所以得出结论,假如要触发tree-shaking
,需求经过解构的办法触发。
3、开启production形式
细心的同学其实能够发现,上面第一点事例中,经过import
的办法导入了compute.js
文件,main.js
代码中虽然没有了sub
办法,但是compute.js
依然会把sub
办法打包
这是由于webpack
对同一文件中的tree-shaking
有必要要开启production
形式才干收效
// webpack.config.js
const path = require("path");
module.exports = {
mode: "production", //出产形式
entry: "./src/main.js",
output: {
path: path.resolve(__dirname, "./dist"),
filename: "bundle.js",
},
};
再次履行打包,发现sub
办法现已不存在了,而且代码还进行了紧缩
4、总结
经过上面的几个事例,webpack
假如要实现tree-shaking
有必要满意以下几个条件:
- 经过
ES6
的import
和export
,包括npm
包也有必要是ESM
- 经过解构的办法引进
- 同一文件下,需求开启
production
形式