什麼是前端模組化?

2022年2月9日

💎 加入 E+ 成長計畫 與超過 300+ 位軟體工程師一同在社群中成長,並且獲得更多的軟體工程學習資源

面試中,關於打包工具的相關知識是非常常見的考題,無可避免的可能會被問到,為什麼需要使用到打包工具、或前端工程化的實現,而要回答這些問題前,需要先了解的就是前端模組化。所以在本篇筆記中,會讓大家了解前端模組化的演進和功用。

什麼是模組化?

開發人員將程式碼或系統分割為不同模組的過程,就稱為模組化。每個模組就代表一個完整的小程序或小功能,所有模組組裝起來成為一個整體,進而完成整個系統的功能要求。

Node.js 幾乎一開始就支持模組化,相比之下 Web 開發,模組化應用進展慢了許多,但到今日也出現了許多支持前端模組化的工具。

為什麼需要前端模組化?

我們先來想像如果今天不用打包工具、模組化語法,要如何在瀏覽器上執行 JavaScript?

  • 方法一:每個功能就是一個 JavaScript script 檔案並載入。但此方法會讓程式碼難以擴展,載入太多 script 也會導致網路瓶頸,並且也有載入先後順序的相依性問題。
  • 方法二:使用一個統一的大 .js 檔案,將所有功能都包含在其中,但這會導致維護、易讀性方面的問題。

模組化工具出現之前,會透過一些方案來解決上述的做法問題,最常見的就是透過立即執行函式(IIFE),它其實是利用函式的閉包特性來實踐數據私有化和共享方法,如下範例

const muduleB = (function () {
  return {
    number: 200,
  };
})();

const moduleA = (function (otherModule) {
  let number = 100;

  function getNumber() {
    console.log(number + otherModule.number);
  }

  return { getNumber };
})(muduleB);

我們可以透過 moduleA 拿到 getNumber 方法,並且實踐 number 變數的私有化,防止外部調用,此外 moduleA 也可以引入其他 module ,通過這種方式,我們就可以在 moduleA 中使用其他模組,進而解決很多問題。

moduleA.getNumber(); // 300
moduleA.number; // undefined

IIFE 的做法也成為現在模組化的概念來源。但隨著前端對模組需求越來越大,逐漸出現了一些模組化解決方案、並演變成了通用的規範,從 CommonJS 到現在的 ES Module(ESM)。下個段落會介紹各個通用的模組化規範

延伸閱讀:JavaScript 立即調用函式 IIFE (Immediately Invoked Function Expression) 是什麼?優缺點是什麼?

JS 模組化規範

CommonJS

Node.js 發佈時,它帶來了新的挑戰。因為 JavaScript 不是在瀏覽器中運行,因此沒有可以添加到其中的 html 文件和腳本標籤,那麼 Node 應用程序應該如何加載不同的程式碼呢?- 透過 CommonJSCommonJS 規範在 2009 年被社群開發出來,引入了 requireexport宣告模組的語法,一個文件就是一個模組,是以同步的方式載入模組,因此適合伺服器端的開發。

AMD(Async Module Definition)

AMD 在中文是非同步模組定義的意思。它起源於 Dojo 工具箱 (一套 JavaScript Web 應用程式庫)。同時,AMD 一開始就是為瀏覽器而設計的,目前為止,最受歡迎的 AMD 實作是 RequireJS (一個 JavaScript 模組加載器)。AMD 可以自動決定相依關係,模組是以非同步方式載入,避免阻塞的問題,並且可以把多個模組定義在同一個檔案中。

CMD(Common Module Definition)

CMD 的出現較晚一些, Sea.js 在 2012 年開始推廣,它汲取了 CommonJSAMD 規範的優點,也是專門用於瀏覽器的異步模塊加載。在規範中,一個文件就是一個模組。

UMD(Universal Module Definition)

AMDCommonJS 是最受歡迎的兩套模組標準,也各有優缺點,通常開發者會根據自己的需求選擇不同的標準。但是,我們也有可能會去使用到不同標準所開發出來的程式碼,這可能就會造成問題。一種解決方案就是 UMD,它可以讓 AMDCommonJS 使用同一份檔案。

ES Module(ESM)

ES6 發佈之後,終於實現了模塊的功能,並結合了 CommonJSAMD 的兩者優點

  • 類似 CommonJS,引入簡單的語法如 exportimport,並且也是一個檔案為一個模組
  • 類似於 AMD 也有支援非同步載入

模組打包工具(Module Bundler)的作用

上個段落介紹了不同模組規範,以及 RequireJS 等模組加載工具被創建,讓我們能在瀏覽器中使用模組。然而,雖然有這些模組化工具,因為各家瀏覽器支援度不同等問題,導致有時候如果你想用別人寫好的模組 (例如 npm 上的套件),很可能沒辦法順利引用。

因為有瀏覽器模組機制相容性、兼容性的問題,前端業界後來發展出 webpack 等工具,協助開發者打包模組,所以假如你的程式碼中,有使用某個 npm 的套件,webpack 會協助你打包,讓他變得像是你自己寫的模組,這有效解決瀏覽器模組功能支援度的問題。

除此之外, webpack 這類的不只幫助我們加載管理程式碼的模組。它進一步擴展到可以支援不同的資源載入,讓各種不同資源都可以變成一個模組 (如:圖像、字體和樣式表)。此外,它可以有其他優化,提供更好的使用者和開發者體驗。


相關文章

🧵 如果你想收到最即時的內容更新,可以在 FacebookInstagram 上追蹤我們