Webpack | 實測 Tree Shaking 針對不同 Import、Export 情境的 Bundle 結果分享

00如是說
Coding Fighter
Published in
5 min readJun 24, 2021
Photo by Brandable Box on Unsplash

前言:

為什麼會寫這篇文章呢?因為自己先前在研究前端效能調校的時候,剛好有看到「不同的 Import 、Export 方式,對 Tree Shaking 是有影響的」,因此好奇想找找網路上有沒有各種情境下,Tree Shaking 的效果比較。

但找了一陣子都只有找到一些簡單的範例,而比較舊的文章也有可能因為 Webpack 的版本不一樣而有不同的結果,因此就想說乾脆自己用最新版的測試各種結果,然後一併分享給大家好了。

所以這篇不會說到什麼很艱深的理論部分,就是單純分享各種情況下的結果給大家參考看看。

怕有人不知道什麼是 Tree Shaking,大致介紹一下就是:「在打包過程中,刪除你沒有用到的程式碼,以減少產生出來的 bundle 體積。」

目錄

  1. 前置作業
  2. 有 Side Effects 的 Function
  3. 沒有 Side Effects 的 Function
  4. 「named export」&「default export」
  5. 「Class」&「非 Class」

前置作業

開始實測前,我們先建好專案以及配置好設定、環境以及結構。

結構大致如下:

webpack-test
|- /node_modules
|- /src
|- demo1
|- /dist
|- index.js // 入口文件
|- xxx.js... // 一個或多個會用到的 js 檔案
|- demo2...
|- package.json
|- webpack.config.js

再來我們根據官方文件配置一些關於 Tree Shaking 的設定:

有 Side Effects 的 Function

這裡因為 console.log 的關係造成了 Side Effects,但 Webpack 打包的結果是執行 add1 之後得到的結果 101,而不是把這個 Function 打包進去,直接優化減少了一個 Execution context。

沒有 Side Effects 的 Function

雖然 add1(100) 有被 invoked,但即使拿掉也沒任何影響,看來 Webpack 是成功移除了。

「named export」&「default export」

named export + import * as

這裡雖然 add2 不見了( 因為沒有 console.log 這個 Side Effect ),但有一點不同的是 add1( 也就是 n )被打包進去了,而且有 n(100),不像之前是完全被移除了。

named export + import { }

這裡雖然 add2 不見了( 因為沒有 console.log 這個 Side Effect ),但有一點不同的是 add1( 也就是 n )被打包進去了,而且有執行 n(100),不像之前是完全被移除了。

default export + import + function 不先包在一個物件

default export + import + function 先包在一個物件

這裡發現兩個問題:

  1. 用 default export 匯出,不知為何跑出了 const
  2. 用 default export 匯出,先包成 Object 再 export 居然會對 Tree Shaking 有影響

來一個 named export + 先包成 Object 再 export 的比對一下

可以看到似曾相似,只有 add1 存在。

第一點先不討論,但就以第二點來說,要使用 default export 似乎需要注意一下。

「Class」&「非 Class」

Class 通常都使用 「 default export」來做導出,因此這裡以此為例

Class

非 Class

以實測結果來看, 「Class」 的範例,不管 function 有沒有使用都被打包進去了,看來 Webpack 對於 Class 的 Tree Shaking 似乎是不太友善?尤其是當這個 JS 是一個龐大的函式庫,可能會打包了很多不必要的 function。

相反地,「非 Class」的範例就非常乾淨。

這裡我其實有驚訝到,因為本身原先是寫 Java 的,所以看到 ES6 有 Class 的語法糖時,就馬上在新專案裡面搞了一堆 Class 😂,沒想到測試後是這個結果。

最後總結一下自己的觀點:

  1. 有多個東西要 export,用 named export 加上一般的 import ( 解構 ) 比較好
  2. 除非只有一個東西要 export,否則不要亂用 default export,而且使用時不要先用 Object 包起來,因為 Javascript 訪問 Object’s property 的方式太多了,很難做到完整的 Tree shaking。
  3. 如果不是要寫 OOP,要衡量一下是否真的需要使用 Class

結論

透過這個實測發現了一些很有趣的狀況,希望這篇文章可以幫助到跟我有相同疑問的人,然後如果有說錯或是說得不好的地方再麻煩指正一下 😂,感謝大家!!

--

--