自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

精準(zhǔn)的打包—Webpack 的 Tree Shaking

開發(fā) 前端
前陣子在和朋友聊 Webpack 的時(shí)候,突然提到 Tree Shaking,但很慚愧的是我沒有辦法好好說明 Webpack 是如何做到 Tree Shaking 的,因此就趁這個(gè)年假的第一天抽空讀 Webpack 的文件,然后把理解到的心得寫下來,如果你也有興趣,就一起看下去吧 。

前陣子在和朋友聊 Webpack 的時(shí)候,突然提到 Tree Shaking,但很慚愧的是我沒有辦法好好說明 Webpack 是如何做到 Tree Shaking 的,因此就趁這個(gè)年假的第一天抽空讀 Webpack 的文件,然后把理解到的心得寫下來,如果你也有興趣,就一起看下去吧 。

Tree Shaking 是什麼

Tree Shaking 是個(gè)優(yōu)化的方式,在 JavaScript 中用來表示移除沒用的代碼的一個(gè)常見術(shù)語,之所以叫做 Tree Shaking 的由來似乎是指說“當(dāng)你大力搖晃一棵樹的時(shí)候,樹上就只會(huì)留著綠色的葉子,其他枯葉都會(huì)落到地上”,而那些綠色的葉子就是打包過后的文件中,真正有用到的代碼。

在使用時(shí)要注意的是,Tree Shaking 只能夠使用在 static structure(例如:import 和 export 上),像是dynamic structure的 require 就沒辦法被偵測(cè)到。舉例來說,import 要載入某個(gè) module 使用的話就一定要在文件的最上方,但 require 可以在任何地方使用,例如以下場(chǎng)景就必須要等到 runtime才會(huì)知道 module 是什么:

let module = null;

if (Math.random() * 10 > 5) {
module = require('module1');
} else {
module = require('moudle2');
}

那開始了解 Tree Shaking 的工作前,應(yīng)該會(huì)有些人好奇,就算自己從來就沒有特別在 Webpack 中設(shè)置 Tree Shaking,但是沒有用的代碼也都會(huì)被移除呀!

那是因?yàn)?Tree Shaking 的執(zhí)行需要 ModuleConcatenationPlugin(圖一),而 Webpack 里另外有個(gè) mode,如果你一直沒有特別去設(shè)置 mode 的值,那 mode 就預(yù)設(shè)會(huì)是 production(圖二),然后 production 的預(yù)設(shè)選項(xiàng)中就會(huì)開啟 ModuleConcatenationPlugin(也是圖二),因此平常不會(huì)特別注意到也不奇怪,因?yàn)?Webpack 都幫你做好了。

Tree Shaking 的運(yùn)作

因?yàn)?Production 會(huì)幫你打開 ModuleConcatenationPlugin ,所以待會(huì)我們實(shí)驗(yàn)的時(shí)候,要把 mode 改成 none(Webpack 文件說 none 為關(guān)掉所有優(yōu)化設(shè)置的模式)。

這邊會(huì)附上簡單的 初始化示例配置,有興趣的話,可以把它 clone 下來一起玩看看。

首先在 src 下建立一個(gè) math.js 和 string.js,接著個(gè)別寫下一個(gè)方法做export,分別是 add 和 composeString:

const add = (a, b) => a + b;

export default { add };
const composeString = (a, b) => `${a} ${b}`;

export default { composeString };

打開 src 下的 index.js,把 add 和 composeString 都 import,但只使用add 方法:

import { add } from './math';
import { addString } from './string';

console.log(add(1, 2))

最后到 terminal 中執(zhí)行 npm run build 或是 webpack 做打包,打包結(jié)束后,會(huì)發(fā)現(xiàn)雖然我們只有import add 做使用,但是打包后的檔案內(nèi)容還是會(huì)有composeString:

不過這很正常,畢竟我們還沒有做任何處理,Webpack 在打包時(shí)也不曉得你哪些代碼到底有沒有用到,就沒辦法幫你把 composeString 移除。

那么到底什么樣的代碼是有用的,怎樣是沒用的呢??

最明顯的定義應(yīng)該是,如果有被執(zhí)行就代表有用到。像是上面例子的 add一樣。

有 side effect 的代碼也是被用到的。像是上方的 index.js,看起來什么方法都沒有提供,但是執(zhí)行時(shí)卻會(huì)在 console 中留下 log,除此之外,會(huì)改變執(zhí)行環(huán)境的 polyfill 也是有 side effect 的 library。

第一種情況相對(duì)容易分辨,但如果是第二種情況的話,可以選擇用 Webpack 中的 sideEffects 屬性來設(shè)置。

sideEffects

sideEffects 可以被設(shè)置為 Boolean 或是 Array,當(dāng)你把它設(shè)置為 false 的時(shí)候,代表該項(xiàng)目是不會(huì)有 sideEffects 的,也就是一律用 export 判斷是否使用。另外 sideEffects 會(huì)依賴 providedExports,用來找出項(xiàng)目中所有 export的 module:

以下是 sideEffects 的使用方式:

{
"name": "tree-shaking",
"sideEffects": false,
"version": "1.0.0",
...
}

只要在package.json中加上 sideEffects,并且將值設(shè)定為 flase,就代表該項(xiàng)目內(nèi)所有的代碼都沒有 side effect,因此 Webpack 在打包的時(shí)候,就可以把沒有用到的 export 代碼給移除。

加上 sideEffects 后打包,就不會(huì)看到 composeString 在結(jié)果裡了:

那現(xiàn)在我們?cè)俚?src 中建立另一個(gè)polyfill.js,在ployfill.js 里為 Array 建立自定義的方法,再把它 import 到index.js 中:

index.js

import './polyfill';
import { add } from './math';
import { addString } from './string';

console.log([].customMethod());

**polyfill.js **

Array.prototype.customMethod = () => {
console.log('customMethods');
};

如果我們?nèi)ゴ虬戏降拇a,polyfill.js 會(huì)因?yàn)闆]有任何 export,所以不會(huì)被providedExports 抓到,也就不會(huì)被打包到 Production,這會(huì)導(dǎo)致項(xiàng)目如果有使用到 Array 的 customMethod,在執(zhí)行時(shí)就會(huì)出錯(cuò)。面對(duì)這種情況,就必須要在 sideEffects 屬性中告知,polyfill.js 是有 side effect 的。設(shè)置方法如下:

{
"name": "tree-shaking",
"sideEffects": ["./src/polyfill.js"],
"version": "1.0.0",
...
}

如此一來,polyfill.js 就會(huì)直接被打包了:

最后要注意兩件事情:

如果各位的項(xiàng)目中也有 import.css 樣式來用的話,也記得要將 .css 結(jié)尾的文件名放到 sideEffects,例如 sideEffects: ["*.css"]。

在webpack.config.js 裡的 optimization 也有 sideEffects,但在這裡設(shè)置的值是針對(duì) node_modules 中的。

useExported

useExported 的作用和 sideEffects 都是用來判斷是否該移除代碼,但根據(jù) Webpack 文件內(nèi)的說明,useExported 才是真正的 Tree Shaking:

usedExports 會(huì)使用 terser 判斷代碼有沒有side effect,如果沒有用到,又沒有side effect 的話,就會(huì)在打包時(shí)替它標(biāo)記上unused harmony,并在minify(用 Uglifyjs 或其他工具)的時(shí)候移除。

在測(cè)試 usedExports 之前,先到math.js 裡加入 square 并 export:

const add = (a, b) => a + b;

const square = (a, b) => a * b;

export { add, square };

接下來到 webpack.config.js 中加入optimization.usedExports:

module.exports = {
...
optimization: {
usedExports: true,
}
};

然后對(duì)項(xiàng)目進(jìn)行打包,就會(huì)發(fā)現(xiàn)僅僅是 export,但沒有使用的 square 會(huì)被標(biāo)記上 unused harmony export:

接著我們使用 uglifyjs-webpack-plugin,把沒有用到的 square 從樹上搖晃下來:

npm install -d uglifyjs-webpack-plugin

webpack.config.js的設(shè)置如下:

const UglifyJsPlugin = require('uglifyjs-webpack-plugin');

module.exports = {
...
optimization: {
usedExports: true,
minimize: true,
minimizer: [
new UglifyJsPlugin({
uglifyOptions: {
compress: { unused: true },
mangle: false,
output: {
beautify: true
}
},
})
],
}
};

設(shè)置完 minimizer 后,再打包一次,就能看見 square 已經(jīng)被移除了:

usedExports 與 sideEffects 不同的是,usedExports 可以以陳述句為單位去判斷是否有 side effect,但是 sideEffects 可以讓 Webpack 在打包的時(shí)候,直接略過一整個(gè)文件,只要是出現(xiàn)在 sideEffect 裡的文件就是直接打包,也不用透過 terser 評(píng)估副作用。

總結(jié)

Tree Shaking 只能在static structure使用,如果項(xiàng)目中的 babel 會(huì)將static structure 編譯成dynamic structure 的話,要另外設(shè)置。

使用 sideEffects 時(shí),要寫在package.json,如果是要對(duì)第三方函式庫優(yōu)化,要寫在 webpack.config.js裡的 optimization。

usedExports 才是 Tree Shacking,使用時(shí)會(huì)自動(dòng)判斷沒使用的代碼,并標(biāo)記 unused harmony 的注解,要移除的話要另外使用 minify。

作者:神Q超人 譯者:前端小智 來源:medium

原文:https://medium.com/starbugs/%E7%B2%BE%E6%B96%E7%9A%84%E6%89%93%E5%8C%85-webpack-%E7%9A%84-tree-shaking-ad39e185f284


責(zé)任編輯:武曉燕 來源: ·前端小智
相關(guān)推薦

2021-06-28 07:01:50

Webpack 前端Tree shakin

2021-08-26 10:30:29

WebpackTree-Shakin前端

2022-06-01 12:04:02

項(xiàng)目Webpack

2025-01-13 00:00:00

2022-05-03 20:48:17

Webpackcommonjsesmodule

2021-12-24 08:01:44

Webpack優(yōu)化打包

2020-07-10 12:06:28

WebpackBundleless瀏覽器

2021-12-25 22:29:04

WebpackRollup 前端

2021-10-12 09:52:30

Webpack 前端多進(jìn)程打包

2024-05-27 00:00:01

2021-12-16 22:02:28

webpack原理模塊化

2021-06-28 05:59:17

Webpack 前端打包與工程化

2022-03-08 09:16:20

webpack前端開發(fā)

2021-10-11 07:55:42

瀏覽器語法Webpack

2023-01-04 08:33:31

Linuxtree命令

2015-06-11 11:18:04

友盟精準(zhǔn)推送

2022-06-10 09:30:59

IBM

2022-08-26 13:24:03

version源碼sources

2019-08-15 10:17:16

Webpack運(yùn)行瀏覽器

2021-08-07 07:23:08

Webpack中間件模型
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)