Skip to main content

[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": [
[
"env",
{
"modules": false
}
]
]
}

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

STEP2: Webpack production mode

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

$ npx webpack -p

或者在 webpack.config.js 的設定檔中,設定 modeproduction

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

資料來源