寶,如何動態導入ECMAScript模塊?

做者:Dmitri Pavlutin
譯者:前端小智
來源:dmitripavlutin

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

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

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

ES模塊系統有2個部分:面試

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

import 模塊是使用 import 語法導入依賴項的模塊:promise

import { concat } from './concatModule';

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

而被導入的模塊使用export語法從自身導出組件:瀏覽器

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

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

雖然靜態導入在大多數狀況下是有效的,但有時咱們想節省客戶的帶寬並有條件地加載模塊。ecmascript

爲了實現這一點,咱們能夠用不一樣的方式使用 import(pathToModule) 語法對模塊進行新的動態導入:做爲一個函數。動態導入是ES2020開始的一個JavaScript語言特性。異步

1. 動態模塊的導入

import關鍵字用做函數而不是靜態導入語法時:async

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。

相關文章
相關標籤/搜索