如何動態匯入ECMAScript模組

前端小智發表於2022-05-23
作者:Dmitri Pavlutin
譯者:前端小智
來源:dmitripavlutin

有夢想,有乾貨,微信搜尋 【大遷世界】 關注這個在凌晨還在刷碗的刷碗智。

本文 GitHub https://github.com/qq449245884/xiaozhi 已收錄,有一線大廠面試完整考點、資料以及我的系列文章。

ECMAScript(又名ES2015或ES)模組是在JavaScript中組織內聚程式碼塊的一種方法。

ES模組系統有2個部分:

  • import模組 - 使用 import { func } from './myModule'
  • export模組- 使用 export const func = () => {}

import 模組是使用 import 語法匯入依賴項的模組:

import { concat } from './concatModule';

concat('a', 'b'); // => 'ab'

而被匯入的模組使用export語法從自身匯出元件:

export const concat = (paramA, paramB) => paramA + paramB;

import { concat } from './concatModule'使用ES模組的方式是靜態的:意味著模組之間的依賴關係在編譯時就已經知道了。

雖然靜態匯入在大多數情況下是有效的,但有時我們想節省客戶的頻寬並有條件地載入模組。

為了實現這一點,我們可以用不同的方式使用 import(pathToModule) 語法對模組進行新的動態匯入:作為一個函式。動態匯入是ES2020開始的一個JavaScript語言特性。

1. 動態模組的匯入

import關鍵字用作函式而不是靜態匯入語法時:

const module = await import(pathToModule);

它返回一個promise ,並開始一個載入模組的非同步任務。如果模組被成功載入,那麼promise就會解析到模組的內容,否則,promise 就會被拒絕。

請注意,pathToModule可以是任何表示式,其值為表示匯入模組路徑的字串。有效的值是普通的字串字面意義(如./myModule)或有字串的變數。

例如,我們在一個非同步函式中載入一個模組。

async function loadMyModule() {
  const myModule = await import('./myModule');
  // ... use myModule
}

loadMyModule();

有趣的是,與靜態匯入相反,動態匯入接受以模組路徑求值的表示式

async function loadMyModule(pathToModule) {
  const myModule = await import(pathToModule);
  // ... use myModule
}

loadMyModule('./myModule');

現在,瞭解瞭如何載入模組後,我們來看看如何從匯入的模組中提取元件。

2.匯入元件

2.1 匯入命名元件

考慮下面的模組:

// namedConcat.js
export const concat = (paramA, paramB) => paramA + paramB;

這裡匯出了一個 concat 函式。

如果想動態匯入namedConcat.js,並訪問命名的匯出concat,那麼只需通解構的方式就行了:

async function loadMyModule() {
  const { concat } = await import('./namedConcat');
  concat('b', 'c'); // => 'bc'
}

loadMyModule();

2.2 預設匯出

如果模組是預設匯出的,我們可以使用default屬性來訪問。

還是上面的例子,我們將defaultConcat.js裡面的concat函式預設匯出:

// defaultConcat.js
export default (paramA, paramB) => paramA + paramB;

在動態匯入模組中,可以使用default屬性來訪問:

async function loadMyModule() {
  const { default: defaultImport } = await import('./defaultConcat');
  defaultImport('b', 'c'); // => 'bc'
}

loadMyModule();

注意,default在JavaScript中是一個關鍵字,所以它不能用作變數名。

2.3匯入混合形式

如果模組裡面既有預設匯出也有命名匯出,同樣也是使用解構的方式來訪問:

async function loadMyModule() {
  const { 
    default: defaultImport,
    namedExport1,
    namedExport2
  } = await import('./mixedExportModule');
  // ...
}

loadMyModule();

3.何時使用動態匯入

建議在模組比較大的,或者要根據條件才匯入的模組可以使用動態匯入

async function execBigModule(condition) {
  if (condition) {
    const { funcA } = await import('./bigModuleA');
    funcA();
  } else {
    const { funcB } = await import('./bigModuleB');
    funcB();
  }
}

execBigModule(true);

對於小模組(如前面例子中的namedConcat.jsdefaultConcat.js),只有幾十行程式碼,使用動態匯入在點殺雞用牛刀感覺。

總結

當呼叫 import(pathToModule) 作為一個函式時,其參數列示一個模組的指定符(又稱路徑),那麼就會動態載入該模組。

在這種情況下,module = await import(pathToModule) 返回一個 promise ,該承諾解析為一個包含匯入模組元件的物件。

Node.js(13.2及以上版本)和大多數現代瀏覽器都支援動態匯入。


編輯中可能存在的bug沒法實時知道,事後為了解決這些bug,花了大量的時間進行log 除錯,這邊順便給大家推薦一個好用的BUG監控工具 Fundebug

原文:https://dmitripavlutin.com/ec...

交流

文章每週持續更新,可以微信搜尋【大遷世界 】第一時間閱讀,回覆【福利】有多份前端視訊等著你,本文 GitHub https://github.com/qq449245884/xiaozhi 已經收錄,歡迎Star。

相關文章