lodash | 如何正確的 import lodash

feat. babel-import-plugin, lodash-es

Leo Chiu
Starbugs Weekly 星巴哥技術專欄
8 min readJun 20, 2021

--

前言

通常前端都會導入一些好用的第三方套件,但是有時後導入的套件並非是基於 es module 進行開發,webpack 沒辦法發揮 tree shaking 的功能,在 import 時一不注意就會載入一堆沒有必要的 function。

在這篇文章中以 lodash 作為舉例, lodash 是個能夠幫我們處理各種資料的函式庫,減少寫一些比較瑣碎的程式碼。但因為 lodash 在 2012 年就被開源,歷史較為久遠,可能有多種緣故,導致目前 lodash 本身並不是使用 es module。所以如果在意 bundle size 的大小,就要特別注意在 import lodash 的方式。

接下來,我們就來看看, 用不同的方式 import lodash 會有什麼不一樣的結果吧!

前置作業

選擇一個簡易 webpack 設定的專案

以下這個專案是我在 rwieruch 上看到一篇文章 How to React with Webpack 5 — Setup Tutorial 中使用的範例程式,我們從 GitHub 上把這個專案下載下來。

這個專案雖然很簡易,但已經足夠讓我們測試並分析不同的 import 方式對於 bundle size 的影響。

下載完後,安裝我們需要的 lodash :

yarn add lodash

webpack bundle analyzer

在分析之前,先來介紹一款分析打包結果的視覺化套件 — webpack bundle analyzer,有了這套工具我們就可以清楚地從視覺化的圖案知道每次打包後的檔案大小,可以用來比較不同的 import 方式對 bundle size 會有什麼樣的影響。

https://www.npmjs.com/package/webpack-bundle-analyzer

使用 webpack bundle analyzer 的方式有兩種,分別為安裝與免安裝 😎

👉 方法 1: 免安裝 webpack-bundle-analyzer

如果你想不想在專案中多安裝一個 webpack 的套件,可以使用方法 1。首先,我們在 package.jsonscripts 中加入一段新的指令:

加入這段指令以後,就可以在終端機中輸入下面兩行指令:

yarn analyze
npx webpack-bundle-analyzer stats.json

在預設的設定下,你應該可以看到啟動了一個 web server 在 http://127.0.0.1:8888 ,進去後可以看到視覺化打包後的結果囉!

👉 方法 2: 安裝 webpack-bundle-analyzer

yarn add -D webpack-bundle-analyzer

接著,安裝完畢後我們要在 webpack.config.js 中加入一些設定:

然後用 yarn start 啟動 server ,跟方法 1 一樣,除了原本專案的 8080 port 之外,你還會看到在 8888 port 啟動了 webpack-bundle-analyzer。

以上介紹的兩種方法就看你喜歡哪種囉!

分析用不同的方式 import lodash 的結果

第一種方式:不指定 function 的路徑

不指定 function 路徑也就像我們平常使用 named exports 的 module 一樣,我們稍微修改 App.js 的程式碼,在 component 裡面加上 lodashisEmpty

接著,我們用 webpack bundle analyzer 看看使用這種 import 方式的 bundle size 為多少。

很誇張的是,明明只有用到 isEmpty 這個 function,結果 lodash 打包後的檔案大小卻足足有 531KB, 不禁讓人懷疑 isEmpty 是多麽偉大的 function 😆,做了包山包海的事情。

isEmpty 的原始碼: 🔗 lodash/isEmpty.js

第二種方式:指定 function 的路徑

接下來,我們換一種 import 的方式,看看對 bundle size 會有什麼影響。

天哪,換一種方式結果讓 lodash 打包後的大小足足少了 22 倍,這是什麼魔法?

為什麼兩種 import 的方式會導致 bundle size 不一樣

我們必須知道 lodash 是一個使用 UMD (Universal Module Definition) 的套件,這意味著 lodash 並不滿足在 webpack 中的 tree-shaking 必須是 es module 的條件。所以第一種方法實際上會載入完整的 lodash ,最終導致 bundle size 莫名的巨大;而第二種方法就是只載入一個檔案,再從檔案中拿出我們需要的 isEmpty,如此一來就不用擔心載入整包 lodash 的問題。

可是如果都要像第二種方法這樣寫 code 實際上有點麻煩,而且團隊可能一開始沒考慮到這個問題,程式碼已經有多處使用第一種方法,改起來十分麻煩。

以下提供兩種我認為比較簡易的解法,可以用最少量的配置,達到降低 bundle size 的方法。

使用 lodash-es 而不是 lodash

這也是 lodash 的 GitHub 提到的作法,lodash 的 GitHub 中寫道:「Looking for Lodash modules written in ES6 or smaller bundle sizes? Check out lodash-es.」,所以第一種解法便是改用 lodash-es:

你可以看到 bundle size 順利地從 531KB 降低到 24KB 左右,與上面提到的第二種 import 的方法有異曲同工之妙。

至於為什麼第二種 import 方法與用 lodash-es 最終打包後的檔案大小不一樣,這又是另一個議題了。

使用 babel-plugin-import

如果你不想動到大量的程式碼,上面使用 lodash-es 意味者必須全域取代 lodash 的引用,其實有另一個解法是使用 babel 的插件,讓 babel 幫我們從第一種 import 的方式改成第二種。

首先,安裝 babel-plugin-import 這個插件:

yarn add -D babel-plugin-import

然後修改 .babelrc 中的設定:

再用 webpack bundle analyzer 看看打包後的檔案大小,可以看到檔案打小與第二種 import 的方式一樣都是 24.31KB,同樣成功地降低 bundle size。

結論

在這篇文章中我們了解了如何透過 webpack bundle analyzer 分析打包後的檔案,並且透過這個工具看到不同 import lodash 方式對於 bundle size 的影響。

針對如何降低 lodash 被打包後的檔案大小,本文提供兩種方式,分別是使用 lodash-es 全域取代原本 lodash 的引用,或使用 babel-plugin-import 非侵入式的改動大量的程式碼,而是在打包時處理,這兩種方式都可以達到不把完整的 lodash 都打包進 bundle 的結果,就看各位如何選擇囉!

分享就到這邊,如果喜歡我的文章可以幫我拍個幾下手,在閱讀文章時如果有遇到什麼問題,或是有什麼建議,都歡迎留言告訴我,謝謝。😃

--

--

Leo Chiu
Starbugs Weekly 星巴哥技術專欄

每天進步一點點,在終點遇見更好的自己。 Instragram 小帳:@leo.web.dev