webpack 4: import() and CommonJs

譯者: 波比小金剛node

翻譯水平有限,若有錯誤請指出。webpack

原文: medium.com/webpack/web…web

ps: 最近開始整理全部的優質文章翻譯集,固然若是你有好的文章請提 issue,我會找時間翻譯出來。json


wepack4 中的一個重大改變就是針對引入非 ESM 模塊(好比 CommonJS 模塊)時,import() 行爲的不一樣ui

事實上在使用 import() 的時候須要考慮不少場景。spa

可是,讓咱們從幾個命名提示開始:翻譯

  • Source: 包含 import() 表達式的模塊
  • Target: import() 表達式中請求的模塊
  • non-ESM: 沒有設置 __esModule: true 的 CommonJS 或者 AMD 模塊
  • transpiled-ESM: 一個設置 __esModule: true 的 CommonJS 模塊,由於它是從 ESM 轉換而來的
  • ESM: 一個普通的 EcmaScript 模塊
  • strict-ESM: 一個更嚴格的EcmaScript模塊,好比 .mjs
  • JSON: 一個 json 文件

須要考慮如下場景:code

  • (A) Source: non-ESM, transpiled-ESM or ESM
  • (B) Source: strict-ESM (mjs)
  • (1) Target: non-ESM
  • (2) Target: transpiled-ESM (__esModule)
  • (3) Target: ESM or strict-ESM (mjs)
  • (4) Target: JSON

這裏有一些容易理解的例子(和上邊的對照起來):對象

// (A) source.js
import("./target").then(result => console.log(result));

// (B) source.mjs
import("./target").then(result => console.log(result));

// (1) target.js
exports.name = "name";
exports.default = "default";

// (2) target.js
exports.__esModule = true;
exports.name = "name";
exports.default = "default";

// (3) target.js or target.mjs
export const name = "name";
export default "default";

// (4) target.json
{ name: "name", default: "default" }
複製代碼

讓咱們從簡單的開始:webpack4

探討的內容實際就是 webpack4 中 import() 引入不一樣規範的模塊的時候,其處理方式。

A3 and B3: import(ESM)

就是引入一個 ESM 的狀況

ESM 規範實際上覆蓋了這些狀況,他們是惟一的"規範"。

import() 將解析目標模塊的命名空間對象。爲了兼容性,會在其命名空間對象中增長一個 __esModule 標誌,以供轉換後的 imports 使用。

{ __esModule: true, name: "name", default: "default" }
複製代碼

A1: import(CJS)

好比引入一個 CommonJS 模塊

咱們導入一個 CommonJS 模塊,webpack3 僅僅解析 module.exports 的值。而 webpack4 將會人爲的爲其建立一個命名空間對象,使得 import() 能夠一致的解析這個命名空間對象。

CommonJs 模塊的默認導出始終是 module.exports 的值,webpack 容許經過 import 從 CommonJS 模塊獲取屬性,import { property } from 'cjs',因此咱們容許 import()

注意:這種狀況下,default 屬性被默認的default 隱藏。

// webpack 3
{ name: "name", default: "default" }

// webpack 4
{ name: "name", default: { name: "name", default: "default" } }
複製代碼

B1: import(CJS).mjs

在 strict-ESM 中引入 CommonJS 模塊

在 strict-ESM 中,咱們不容許經過 import 獲取屬性,只容許 non-ESM 的默認導出。

{ default: { name: "name", default: "default" } }
複製代碼

A2: import(transpiled-ESM)

引入一個設置 __esModule: true 的 CommonJS 模塊

webpack 經過將 CJS 模塊升級爲 ESM 來支持 __esModule。

{ __esModule: true, name: "name", default: "default" }
複製代碼

B2: import(transpiled-ESM).mjs

在 strict-ESM 中引入 transpiled-ESM

在 strict-ESM 中 __esModule 不被支持。

你能夠把它稱爲破壞,但至少它與 node.js 一致。

{ default: { __esModule: true, name: "name", default: "default" } }
複製代碼

A4 and B4: import(json)

引入 json

在導入 json 的時候,無論是否是 strict-ESM,都支持屬性選擇。json 將完整的對象做爲 default 導出。

{ name: "name", default: { name: "name", default: "default" } }
複製代碼

總結上邊的情景,只有一種狀況發生了改變。當導出對象的時候沒有問題,可是 module.exports 與非對象一塊兒使用的時候,你會遇到麻煩。

好比:

module.exports = 42
複製代碼

你須要使用default屬性:

// webpack 3
42

// webpack 4
{ default: 42 }
複製代碼
相關文章
相關標籤/搜索