今天來介紹 JavaScript 的模組 esm
系統及 commonjs
系統。
當我們的程式越寫越複雜時,不再適合把幾千行的程式碼全部放在同一個檔案內,這樣不僅難以更新維護,發生錯誤時也難以及時發現處理。
所以我們會將程式碼拆成一塊一塊,把相似功能的程式碼放到一個一個檔案中,再一層一層的引用。這樣不僅維護相對容易,在做部分項目更新時也較為方便,避免誤觸不相干的程式碼外,在思考時也較能專注在相關程式碼上。
這樣拆成一個一個的檔案,再用引用的方式使用,我們就可將之稱為模組。
最早 JavaScript 是沒有模組設計的,因為通常都是被 HTML 一個個 <script>
引入使用。
也因此當時爲 JavaScript 設計模組的責任就落到了開發者身上,所以出現許多不同的第三方模組系統,其中較為知名的應該是 commonjs
、umd
及 amd
了。
後來又經過了幾年,在 2015 年時隨著 ES6 的正式發布,JavaScript 終於迎來了標準版本的模組系統,稱為 esm
。
隨著時間的流逝,也因為標準模組系統 esm
的出現,許多第三方模組系統就慢慢被遺棄了。不過,也不是全部的第三方模組系統都被 esm
取代了,像是因為 Node.js 預設使用的模組系統是 commonjs
,所以其生態仍是非常豐富,開發者社群也相當活躍。而 umd
因為可以直接使用,不需要額外的引用方式,在 <script>
可以直接引用的特性,也還是有一定的可見性。
所以接下來會對 esm
及 commonjs
做較為詳細的解說。
esm
作為標準的模組系統,其重要性近年來持續上升,對其的支援也越趨廣泛。
esm
用了非常好懂的 export
及 import
關鍵字來定義模組的匯出物件,以及引用時使用的物件。
常見的 export
方式:
// mod.js
const cool_things = {
c1: "我是常數",
f1() {},
f2() {},
};
export default cool_things;
// or
export { ...cool_things };
兩種 export
的差異在於 import
時的可用性。export default
,可以用任意名稱 import
,而另一個方法則否。
// 使用 export default 時的 import 方法
// 兩者會引入相同東西至不同名稱物件中
import things from "./mod.js";
import something from "./mod.js";
// 使用 export { ... } 時的 import 方法
// 可以選擇引入其中數項,不需全部引入
import { c1, f2 } from "./mod.js"; // 只引入 c1 及 f2
需要注意的是,import
會在一開始時就引入,且會等所有模組皆被引入後再執行其餘程式。
因為 import
的優先引入可能會引入不必要的模組或阻擋主程式的運行,所以 esm
中還有一種動態引用的方法 import()
,其會回傳一個 Promise
包著的 module。
(async () => {
doSomethingWithoutModule();
const mod = await import("./mod.js");
mod.doSomething();
})();
記得要加上 type="module"
attribute 才能使用。
CommonJS 作為 Node.js 長久以來使用的模組系統,當然在使用 Node.js 時會用到啦。
require
是 CommonJS 用來引入模組的函式。
const mod = require("./mod.js");
// 或是只引入部分
const { c1, f2 } = require("./mod.js");
require
可以在任何地方使用,不一定要在檔案最上面引用,可以依判斷條件動態引用不同模組等。
exports
及 module.exports
則是用來匯出模組物件的。
exports
其實就是 module.exports
,就好像是系統已經幫你寫好了 var exports = module.exports;
一樣。
const cool_things = {
c1: "我是常數",
f1() {},
f2() {},
};
// 匯出 cool_things
module.exports = cool_things;
// 或分項匯出
exports.c1 = cool_things.c1;
exports.f1 = cool_things.f1;
exports.f2 = cool_things.f2;
exports.c2 = "我是另一個常數";
其實 exports
物件就可以想成是這個模組對外的介面。
以 9/20 12:00 ~ 9/21 12:00 文章觀看數增加值排名
+321
深入淺出 Computed
+246
Day 2:什麼是 SRE
+210
#1 JavaScript Easy Go!
+205
LeetCode 是什麼?為什麼要刷題?
+204
LeetCode 解題的思考策略與解題地圖
+201
Day 1 無限手套 AWS 版:掌控一切的 5 + 1 雲端必學主題
+199
[Day 02] 什麼是tinyML?
+199
[Day 02] 什麼是tinyML?
+194
#4 Array & Object in JavaScript
+181
Proxmox VE 安裝虛擬機:Windows 10 (一)
AWS 稱霸 2 天後就幾乎全部消失了
說到 LeetCode,讓我想起了 LeetCode Stats Card