本系列文章經過重新編排和擴充,已出書為ECMAScript關鍵30天。原始文章因當時準備時程緊迫,多少有些許錯誤。為了避免造成讀者的困擾,以及配合書籍的內容規劃,將會陸續更新本系列文章。
本篇文章在 2021/11/8 已更新。
在模組化開發下,我們會以import
的方式匯入需要的模組。但是因為import
是屬於靜態函式,如果有些模組是在特定條件下才會用到的話,程式裡面還是會包含到這些模組,某些情況下可能只是徒增執行檔的大小。
不過有些 framework 或打包工具有針對這部分提供了解決方案。像是 React 內建的 lazy
和 suspense
API,或是第三方套件 React Loadable
,讓開發者先享受到動態載入的便利性。
在 ES2020 後,import
終於也可以動態載入。透過 Promise 的包裝,讓在特定條件下執行載入的模組,可以在回傳的 promise 中取得。
btn.onclick = () => {
// promise chaining 的方式
import("./moduleA.js")
.then((module) => {
// Do something with the module.
})
.catch((err) => {
// load error;
});
// 使用await的方式
let module = await import("./moduleA.js");
};
動態匯入 json 檔也可以。
const loadUserProfile = () => import("./user/profile.json");
loadUserProfile().then(
(value) => value?.default && setUserProfile(value.default)
);
如果使用 Babel 轉譯的話,在外掛的列表上需要加上 @babel/plugin-syntax-dynamic-import
。如果有使用 @babel/preset-env
的 preset 的話就不用額外設定。
當要匯入某個檔案的所有輸出函式,為了語意性和方便性,我們會為這些匯入的函式放在一個 namespace 底下。
import * as Util from "../utils";
相對地 export
並沒有支援 namespace。所以我們很常在函式庫的入口處會這樣寫 -
import * as Util from "../utils";
export { Utils };
在 ES2020 後,export
也能像 import
一樣以 namespace 輸出了。
export * as Utils from "../utils";
import.meta
針對匯入的 JS 模組檔案提供相關訊息的物件,像是模組的路徑等。
<script type="module" src="my-module.js"></script>;
console.log(import.meta); // { url: "file:///home/user/my-module.js" }