模組方法

此區段涵蓋 webpack 編譯程式碼中所有可用的方法。當使用 webpack 將應用程式打包時,您可以從各種模組語法樣式中挑選,包括 ES6CommonJSAMD

雖然 webpack 支援多種模組語法,但我們建議遵循單一語法以確保一致性並避免奇怪的行為/錯誤。實際上,當最近的父級 package.json 檔案包含值為 "module""commonjs""type" 欄位時,webpack 會強制執行 .mjs 檔案、.cjs 檔案或 .js 檔案的建議。請在繼續閱讀前注意這些強制執行

  • package.json 中的 .mjs.js,並具有 "type": "module"
    • 不允許 CommonJS,例如,您無法使用 requiremodule.exportsexports
    • 匯入時需要檔案副檔名,例如,您應該使用 import './src/App.mjs' 而不是 import './src/App' (您可以使用 Rule.resolve.fullySpecified 停用此強制執行)
  • package.json 中的 .cjs.js,並具有 "type": "commonjs"
    • importexport 都不可用
  • package.json 中的 .wasm,並具有 "type": "module"
    • 匯入 wasm 檔案時需要檔案副檔名

ES6(建議使用)

webpack 版本 2 原生支援 ES6 模組語法,表示您可以使用 importexport,而不需要像 babel 這樣的工具來處理這些語法。請注意,您可能仍需要 babel 來使用其他 ES6+ 功能。webpack 支援下列方法

import

靜態 import 另一個模組的 export

import MyModule from './my-module.js';
import { NamedExport } from './other-module.js';

您也可以 import 資料 URI

import 'data:text/javascript;charset=utf-8;base64,Y29uc29sZS5sb2coJ2lubGluZSAxJyk7';
import {
  number,
  fn,
} from 'data:text/javascript;charset=utf-8;base64,ZXhwb3J0IGNvbnN0IG51bWJlciA9IDQyOwpleHBvcnQgY29uc3QgZm4gPSAoKSA9PiAiSGVsbG8gd29ybGQiOw==';

export

將任何內容作為 default 或命名 export 匯出。

// Named exports
export var Count = 5;
export function Multiply(a, b) {
  return a * b;
}

// Default export
export default {
  // Some data...
};

import()

function(string 路徑):Promise

動態載入模組。呼叫 import() 會被視為分割點,表示要求的模組及其子模組會分割到一個獨立的區塊中。

if (module.hot) {
  import('lodash').then((_) => {
    // Do something with lodash (a.k.a '_')...
  });
}

import() 中的動態表達式

無法使用完全動態的匯入陳述式,例如 import(foo)。因為 foo 可能是系統或專案中任何檔案的任何路徑。

import() 必須包含模組所在位置的一些資訊。套件可以限制在特定目錄或檔案組,以便在使用動態表達式時 - 每個模組都可能在 import() 呼叫時請求,並包含在內。例如,import(`./locale/${language}.json`) 會導致 ./locale 目錄中的每個 .json 檔案都套件到新的區塊中。在執行階段,當變數 language 已計算完成時,任何檔案(例如 english.jsongerman.json)都可供使用。

// imagine we had a method to get language from cookies or other storage
const language = detectVisitorLanguage();
import(`./locale/${language}.json`).then((module) => {
  // do something with the translations
});

魔術註解

內嵌註解可讓功能運作。透過在匯入中新增註解,我們可以執行命名區塊或選擇不同模式等動作。如需這些魔術註解的完整清單,請參閱下列程式碼,以及這些註解執行的動作說明。

// Single target
import(
  /* webpackChunkName: "my-chunk-name" */
  /* webpackMode: "lazy" */
  /* webpackExports: ["default", "named"] */
  /* webpackFetchPriority: "high" */
  'module'
);

// Multiple possible targets
import(
  /* webpackInclude: /\.json$/ */
  /* webpackExclude: /\.noimport\.json$/ */
  /* webpackChunkName: "my-chunk-name" */
  /* webpackMode: "lazy" */
  /* webpackPrefetch: true */
  /* webpackPreload: true */
  `./locale/${language}`
);
import(/* webpackIgnore: true */ 'ignored-module.js');
webpackIgnore

設為 true 時,停用動態匯入剖析。

webpackChunkName

新區塊的名稱。自 webpack 2.6.0 起,已支援在給定字串中使用 [index][request] 佔位符,分別表示遞增的數字或實際解析的檔案名稱。新增此註解將使我們的獨立區塊命名為 [my-chunk-name].js,而不是 [id].js。

webpackFetchPriority
5.87.0+

針對特定動態載入設定 fetchPriority。也可以使用 module.parser.javascript.dynamicImportFetchPriority 選項,為所有動態載入設定全域預設值。

import(
  /* webpackFetchPriority: "high" */
  'path/to/module'
);
webpackMode

自 webpack 2.6.0 起,可以指定不同的模式來解析動態載入。支援下列選項

  • 'lazy' (預設):針對每個 import()ed 模組產生可延遲載入的區塊。
  • 'lazy-once':產生單一可延遲載入的區塊,可滿足所有對 import() 的呼叫。此區塊會在第一次呼叫 import() 時擷取,後續對 import() 的呼叫會使用相同的網路回應。請注意,這僅在部分動態陳述的情況下才有意義,例如 import(`./locales/${language}.json`),其中有多個模組路徑可能被要求。
  • 'eager':不產生額外的區塊。所有模組都包含在目前的區塊中,且不會產生其他網路要求。仍會傳回 Promise,但已解析。與靜態載入不同,模組不會在呼叫 import() 之前執行。
  • 'weak':如果模組函式已透過其他方式載入 (例如,其他區塊載入它,或載入包含該模組的指令碼),則嘗試載入模組。仍會傳回 Promise,但只有當區塊已存在於客戶端時,才會成功解析。如果模組不可用,則 Promise 會被拒絕。絕不會執行網路要求。當必要的區塊總是手動提供於初始要求 (嵌入在頁面中) 時,這對於通用呈現很有用,但對於應用程式導覽會觸發未在初始提供載入的情況則不然。
webpackPrefetch

告訴瀏覽器此資源未來可能需要用於某些導覽。查看指南以取得更多關於 webpackPrefetch 運作方式 的資訊。

webpackPreload

告訴瀏覽器此資源可能需要在目前導覽期間使用。查看指南以取得更多關於 webpackPreload 運作方式 的資訊。

webpackInclude

在匯入解析期間會比對的正規表示式。只有比對成功的模組才會打包

webpackExclude

在匯入解析期間會比對的正規表示式。任何比對成功的模組都不會打包

webpackExports:告訴 webpack 只打包動態 import()ed 模組指定的 exports。它可以減少區塊的輸出大小。自 webpack 5.0.0-beta.18 起提供。

CommonJS

CommonJS 的目標是為瀏覽器外的 JavaScript 指定一個生態系統。webpack 支援下列 CommonJS 方法

require

require(dependency: String);

同步擷取其他模組的輸出。編譯器會確保相依性在輸出套件中可用。

var $ = require('jquery');
var myModule = require('my-module');

也可以為 require 啟用神奇註解,詳情請參閱 module.parser.javascript.commonjsMagicComments

require.resolve

require.resolve(dependency: String);

同步擷取模組的 ID。編譯器會確保相依性在輸出套件中可用。建議將其視為不透明值,只能與 require.cache[id]__webpack_require__(id) 搭配使用(最好避免這種用法)。

有關更多資訊,請參閱 module.id

require.cache

多次 require 同一個模組只會執行一次模組,只會輸出一次。因此執行階段存在快取。從這個快取中移除值會導致新的模組執行和新的輸出。

var d1 = require('dependency');
require('dependency') === d1;
delete require.cache[require.resolve('dependency')];
require('dependency') !== d1;
// in file.js
require.cache[module.id] === module;
require('./file.js') === module.exports;
delete require.cache[module.id];
require.cache[module.id] === undefined;
require('./file.js') !== module.exports; // in theory; in praxis this causes a stack overflow
require.cache[module.id] !== module;

require.ensure

require.ensure(
  dependencies: String[],
  callback: function(require),
  errorCallback: function(error),
  chunkName: String
)

將指定的 dependencies 分割到一個獨立的套件中,並非同步載入。當使用 CommonJS 模組語法時,這是動態載入依賴項目的唯一方法。也就是說,這段程式碼可以在執行期間執行,僅在符合特定條件時載入 dependencies

var a = require('normal-dep');

if (module.hot) {
  require.ensure(['b'], function (require) {
    var c = require('c');

    // Do something special...
  });
}

以下參數依上述順序提供支援

  • dependencies:宣告 callback 中執行程式碼所需所有模組的字串陣列。
  • callback:Webpack 在載入依賴項後執行的函式。require 函式的實作會作為參數傳送給此函式。函式主體可以使用此函式進一步 require() 執行所需的模組。
  • errorCallback:Webpack 無法載入依賴項時執行的函式。
  • chunkName:給予此特定 require.ensure() 建立的區塊名稱。透過將相同的 chunkName 傳遞給各種 require.ensure() 呼叫,我們可以將其程式碼合併成單一區塊,只產生瀏覽器必須載入的一個套件。

AMD

非同步模組定義 (AMD) 是一種 JavaScript 規格,定義了撰寫和載入模組的介面。Webpack 支援下列 AMD 方法

定義(使用工廠)

define([name: String], [dependencies: String[]], factoryMethod: function(...))

如果提供了 dependencies,則會使用每個依賴項的匯出(按相同順序)呼叫 factoryMethod。如果未提供 dependencies,則會使用 requireexportsmodule 呼叫 factoryMethod(為了相容性!)。如果此函式傳回一個值,則此值會由模組匯出。編譯器會確保每個依賴項都可用。

define(['jquery', 'my-module'], function ($, myModule) {
  // Do something with $ and myModule...

  // Export a function
  return function doSomething() {
    // ...
  };
});

定義(使用值)

define(value: !Function)

這將匯出提供的 value。這裡的 value 可以是任何東西,除了函式之外。

define({
  answer: 42,
});

require (amd 版本)

require(dependencies: String[], [callback: function(...)])

類似於 require.ensure,這會將指定的 dependencies 分割成一個獨立的套件,並會非同步載入。會使用 dependencies 陣列中每個依賴項的匯出呼叫 callback

require(['b'], function (b) {
  var c = require('c');
});

標籤模組

內部的 LabeledModulesPlugin 讓您可以在模組中使用下列方法來匯出和需要

匯出標籤

匯出給定的 value。標籤可以在函數宣告或變數宣告之前出現。函數名稱或變數名稱是匯出值之下的識別碼。

export: var answer = 42;
export: function method(value) {
  // Do something...
};

require 標籤

讓所有從依賴項的匯出在目前的範圍中可用。require 標籤可以在字串之前出現。依賴項必須使用 export 標籤匯出值。無法使用 CommonJS 或 AMD 模組。

some-dependency.js

export: var answer = 42;
export: function method(value) {
  // Do something...
};
require: 'some-dependency';
console.log(answer);
method(...);

Webpack

除了上述的模組語法之外,Webpack 也允許一些自訂的 Webpack 專屬方法

require.context

require.context(
  (directory: String),
  (includeSubdirs: Boolean) /* optional, default true */,
  (filter: RegExp) /* optional, default /^\.\/.*$/, any file */,
  (mode: String) /* optional, 'sync' | 'eager' | 'weak' | 'lazy' | 'lazy-once', default 'sync' */
);

使用路徑到 directory 指定一整組依賴項,includeSubdirs 選項,更精細地控制所包含模組的 filter,以及定義載入方式的 mode。稍後可以解析底層模組

var context = require.context('components', true, /\.html$/);
var componentA = context.resolve('componentA');

如果 mode 設為 'lazy',底層模組將會非同步載入

var context = require.context('locales', true, /\.json$/, 'lazy');
context('localeA').then((locale) => {
  // do something with locale
});

可用模式及其行為的完整清單說明在 import() 文件中。

require.include

require.include((dependency: String));

包含 dependency 而不用執行它。這可以用來最佳化模組在輸出區塊中的位置。

require.include('a');
require.ensure(['a', 'b'], function (require) {
  /* ... */
});
require.ensure(['a', 'c'], function (require) {
  /* ... */
});

這將會產生下列輸出

  • 進入區塊:file.jsa
  • 匿名區塊:b
  • 匿名區塊:c

沒有 require.include('a'),它會在兩個匿名區塊中重複。

require.resolveWeak

類似於 require.resolve,但這不會將 module 拉入套件中。它被認為是「弱」依賴項。

if (__webpack_modules__[require.resolveWeak('module')]) {
  // Do something when module is available...
}
if (require.cache[require.resolveWeak('module')]) {
  // Do something when module was loaded before...
}

// You can perform dynamic resolves ("context")
// similarly to other require/import methods.
const page = 'Foo';
__webpack_modules__[require.resolveWeak(`./page/${page}`)];

警告

如果模組來源包含無法靜態分析的需要,則會發出關鍵依賴項警告。

範例程式碼

someFn(require);
require.bind(null);
require(variable);

10 貢獻者

skipjacksokrafadysamirsadekbyzykdebs-obrienwizardofhogwartsEugeneHlushkochenxsanjamesgeorge007WofWca