跳至主要内容

[GoogleDeveloper] Reduce JavaScript Payloads with Tree Shaking

Tree Shaking 是什麼?​

Tree Shaking 這個是自從 Rollup 紅過來的,指的是把沒用到的程式碼從 bundle 中移除(dead code elimination)。

// Import all the array utilities!
import arrayUtils from 'array-utils';
// Import only some of the utilities!
import { unique, implode, explode } from 'array-utils';

這兩段程式碼一個會把整個 library 載入,另一個則是只會載入有用到的函式。在開發模式下,這兩個的打包的結果會是一樣的;然而,在正式環境(production mode),可以在 webpack 中把其他沒有載入到的模組移除,讓正式環境打包出來的檔案更輕巧。

透過 Tree Shaking,只有實際上有使用到的模組(程式碼)才會出現在最後打包好的檔案。

使用 Tree Shaking​

STEP1: 讓 Babel 不編譯和模組相關的關鍵字​

由於使用 Tree Shaking 時必須讓 webpack 能夠認懂 import 這個關鍵字,因此如果我們有使用 babel 的話,需要讓 babel 不要轉譯和模組相關的關鍵字:

// .babelrc
{
"presets": [
[
"@babel/preset-env",
{
"modules": false
}
]
]
}

當你在 babel-preset-env 的設定檔 .babelrc 中加上 "modules": false 後,webpack 就可以分析你的相依樹(dependency tree)並且移除掉沒有被使用到的套件。更進一步,這麼做並不會影響到程式碼的相容性(compatibility),因為 webpack 最後會很聰明的將你的程式碼轉換為可相同的格式。

STEP2: Webpack production mode​

當 webpack 以 production mode 執行時,即會自動執行 tree shaking 的功能:

$ npx webpack --mode production

或者在 webpack.config.js 的設定檔中,設定 mode 為 production:

module.exports = {
...,
mode: "production",
...,
};

STEP3: 留意可能的 side effects​

side effect 指的是有些程式碼是在被 imported 的時候就執行了某些行為,而非和任何的 export 有關,這個 module 本身在執行時就直接影響到了整個 global scope。最常見會有 side effect 的套件是 polyfill。Polyfill 通常不會在主要的 scripts 中提供 export 方法,而是要把它放到整個專案中使用。

但是 Tree shaking 沒辦法自動判斷哪些程式碼是有 side effect 的,所以必須手動告知它。例如定義在 package.json 中:

// package.json
{
...,
"sideEffects": [
"./src/polyfill.js"
],
...,
}

Keeping Side Effects in Mind @ Google Developers

資料來源​