如何動態導入 ECMAScript 模塊
ES 模塊系統有 2 個角色:
-
導入 - import {func} from './myModule.js'
-
導出 - export const func = () => {}。
導入模塊使用 import 語法導入依賴項:
// The importing module
import { concat } from './concatModule.js';
concat('a', 'b'); // => 'ab'
導入的模塊本身是用 export 語法導出的模塊:
// The imported module exports components
export const concat = (paramA, paramB) => paramA + paramB;
使用 ES 模塊的方式是靜態的:這意味着模塊之間的依賴關係在編譯時是已知的。
雖然靜態導入在大多數情況下都有效,但有時也會遇到動態加載模塊的情況。
如果 import 用作函數,則可以動態導入模塊— import(pathToModule). 動態導入是 ES2020 開始的 JavaScript 語言功能。
1. 模塊的動態導入
當 import 關鍵字用作函數而不是靜態導入語法時:
const module = await import(path);
它返回一個 Promise 並啓動一個異步任務來加載模塊。如果模塊成功加載,則 Promise 解析爲模塊內容,否則, Promise 拒絕。
path 可以是任何計算結果爲指示路徑的字符串的表達式。有效的路徑表達式是:
// Classic string literals
const module1 = await import('./myModule.js');
// A variable
const path = './myOtherModule.js';
const module2 = await import(path);
// Function call
const getPath = (version) => `./myModule/versions/${version}.js`;
const moduleVersion1 = await import(getPath('v1.0'));
const moduleVersion2 = await import(getPath('v2.0'));
因爲 import(path) 返回一個 Promise ,它非常適合 async/await 語法。例如,讓我們在異步函數中加載一個模塊:
async function loadMyModule() {
const myModule = await import('./myModule.js');
// ... use myModule
}
loadMyModule();
2. 導入組件
2.1 命名導出的導入
讓我們考慮以下名爲 namedConcat.js 的模塊:
// namedConcat.js
export const concat = (paramA, paramB) => paramA + paramB;
namedConcat 執行 concat 函數的命名導出。
如果您想動態導入 namedConcat.js 並訪問命名的 export concat,那麼只需通過命名的導出名稱解構解析的模塊對象:
async function loadMyModule() {
const { concat } = await import('./namedConcat.js');
concat('b', 'c'); // => 'bc'
}
loadMyModule();
2.2 導入默認導出
如果導入的模塊作爲默認導出,您可以通過 default 從模塊對象讀取屬性來訪問默認導入。
假設 defaultConcat.js 導出功能作爲 default 導出:
// defaultConcat.js
export default (paramA, paramB) => paramA + paramB;
defaultConcat.js 動態導入時,特別是訪問 default 導出時,您只需要讀取 default 屬性即可。
但有一個細微差別。default 是 JavaScript 中的關鍵字,因此它不能用作變量名,因此您只需使用帶別名的解構:
async function loadMyModule() {
const { default: defaultImport } = await import('./defaultConcat.js');
defaultImport('b', 'c'); // => 'bc'
}
loadMyModule();
2.3 導入混合內容
如果導入的模塊導出 default 和多個命名導出,那麼您可以使用單個解構輕鬆訪問所有這些組件:
async function loadMyModule() {
const {
default: defaultImport,
namedExport1,
namedExport2
} = await import('./mixedExportModule.js');
// ...
}
loadMyModule();
3. 何時使用動態導入
我建議在某些條件下導入大模塊時使用動態導入。
async function execBigModule(condition) {
if (condition) {
const { funcA } = await import('./bigModuleA.js');
funcA();
} else {
const { funcB } = await import('./bigModuleB.js');
funcB();
}
}
execBigModule(true);
對於只有幾十行代碼的小模塊(如 namedConcat.js 或 defaultConcat.js 來自前面的示例),動態導入不值得麻煩。
4. 尾聲
Node.js(版本 13.2 及更高版本)和大多數現代瀏覽器都支持動態導入。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/ei9xPIiObaFkVQV1RLeZiA