外部程式

externals 組態選項提供一種從輸出套件中排除相依性的方式。反之,建立的套件依賴於使用者 (任何終端使用者應用程式) 環境中存在的相依性。此功能通常對函式庫開發人員最有幫助,但它有各種應用程式。

externals

字串 物件 函式 正規表示法 [字串、物件、函式、正規表示法]

防止捆綁某些 import 的套件,而是在執行階段擷取這些外部相依性

例如,要包含 jQuery 從 CDN,而不是將其捆綁

index.html

<script
  src="https://code.jquery.com/jquery-3.1.0.js"
  integrity="sha256-slogkvB1K3VOkzAI8QITxV3VzpOnkeNVsKvtkYLMjfk="
  crossorigin="anonymous"
></script>

webpack.config.js

module.exports = {
  //...
  externals: {
    jquery: 'jQuery',
  },
};

這會讓任何依賴的模組保持不變,也就是說,下面顯示的程式碼仍然會運作

import $ from 'jquery';

$('.my-element').animate(/* ... */);

在上述的 webpack.config.js 中,externals 下指定的屬性名稱 jquery 表示 import $ from 'jquery' 中的模組 jquery 應從捆綁中排除。為了取代此模組,值 jQuery 將用於擷取全域 jQuery 變數,因為預設的外部函式庫類型為 var,請參閱 externalsType

雖然我們在上面顯示了使用外部全域變數的範例,但外部實際上可以採用下列任何一種形式:全域變數、CommonJS、AMD、ES2015 模組,請在 externalsType 中查看更多資訊。

字串

根據 externalsType,這可能是全域變數的名稱(請參閱 'global''this''var''window')或模組的名稱(請參閱 amdcommonjsmoduleumd)。

如果您只定義 1 個外部,也可以使用捷徑語法

module.exports = {
  //...
  externals: 'jquery',
};

等於

module.exports = {
  //...
  externals: {
    jquery: 'jquery',
  },
};

您可以使用 ${externalsType} ${libraryName} 語法,為外部指定 外部函式庫類型。它將覆寫在 externalsType 選項中指定的預設外部函式庫類型。

例如,如果外部函式庫是 CommonJS 模組,您可以指定

module.exports = {
  //...
  externals: {
    jquery: 'commonjs jquery',
  },
};

[字串]

module.exports = {
  //...
  externals: {
    subtract: ['./math', 'subtract'],
  },
};

subtract: ['./math', 'subtract'] 允許您選擇模組的一部分,其中 ./math 是模組,而您的套件只需要 subtract 變數下的子集。

externalsTypecommonjs 時,此範例將轉換為 require('./math').subtract; 而當 externalsTypewindow 時,此範例將轉換為 window["./math"]["subtract"];

字串語法 類似,您可以在陣列的第一個項目中使用 ${externalsType} ${libraryName} 語法指定外部函式庫類型,例如

module.exports = {
  //...
  externals: {
    subtract: ['commonjs ./math', 'subtract'],
  },
};

物件

module.exports = {
  //...
  externals: {
    react: 'react',
  },

  // or

  externals: {
    lodash: {
      commonjs: 'lodash',
      amd: 'lodash',
      root: '_', // indicates global variable
    },
  },

  // or

  externals: {
    subtract: {
      root: ['math', 'subtract'],
    },
  },
};

此語法用於描述外部函式庫可以提供的各種可能方式。此處的 lodash 可用於 AMD 和 CommonJS 模組系統中的 lodash,但可用於全域變數形式中的 _。此處的 subtract 可透過全域 math 物件中的 subtract 屬性取得 (例如 window['math']['subtract'])。

函式

  • function ({ context, request, contextInfo, getResolve }, callback)
  • function ({ context, request, contextInfo, getResolve }) => promise 5.15.0+

定義您自己的函式來控制您要從 webpack 外部化的行為可能很有用。例如,webpack-node-externals 會排除 node_modules 目錄中的所有模組,並提供允許套件的選項。

以下是函式可以接收的引數

  • ctx (object):包含檔案詳細資料的物件。
    • ctx.context (string):包含匯入的檔案目錄。
    • ctx.request (string):正在要求的匯入路徑。
    • ctx.contextInfo (object):包含發佈者的資訊 (例如層和編譯器)
    • ctx.getResolve 5.15.0+:取得具有目前解析器選項的解析函式。
  • callback (function (err, result, type)):用於指示如何將模組外部化的回呼函式。

回呼函式採用三個引數

  • err (Error):用於指出外部化匯入時是否發生錯誤。如果有錯誤,這應該是唯一使用的參數。
  • result (string [string] object):使用其他外部格式 (string[string]object) 描述外部模組
  • type (string):指示模組 外部類型 的選用參數 (如果尚未在 result 參數中指示)。

例如,要外部化所有匯入,其中匯入路徑符合正規表示式,您可以執行下列動作

webpack.config.js

module.exports = {
  //...
  externals: [
    function ({ context, request }, callback) {
      if (/^yourregex$/.test(request)) {
        // Externalize to a commonjs module using the request path
        return callback(null, 'commonjs ' + request);
      }

      // Continue without externalizing the import
      callback();
    },
  ],
};

使用不同模組格式的其他範例

webpack.config.js

module.exports = {
  externals: [
    function (ctx, callback) {
      // The external is a `commonjs2` module located in `@scope/library`
      callback(null, '@scope/library', 'commonjs2');
    },
  ],
};

webpack.config.js

module.exports = {
  externals: [
    function (ctx, callback) {
      // The external is a global variable called `nameOfGlobal`.
      callback(null, 'nameOfGlobal');
    },
  ],
};

webpack.config.js

module.exports = {
  externals: [
    function (ctx, callback) {
      // The external is a named export in the `@scope/library` module.
      callback(null, ['@scope/library', 'namedexport'], 'commonjs');
    },
  ],
};

webpack.config.js

module.exports = {
  externals: [
    function (ctx, callback) {
      // The external is a UMD module
      callback(null, {
        root: 'componentsGlobal',
        commonjs: '@scope/components',
        commonjs2: '@scope/components',
        amd: 'components',
      });
    },
  ],
};

RegExp

與給定正規表示式相符的每個相依性都會從輸出套件中排除。

webpack.config.js

module.exports = {
  //...
  externals: /^(jquery|\$)$/i,
};

在這種情況下,任何名為 jQuery 的相依性 (不分大小寫) 或 $ 都會被外部化。

組合語法

有時您可能想要使用上述語法組合。這可以用下列方式完成

webpack.config.js

module.exports = {
  //...
  externals: [
    {
      // String
      react: 'react',
      // Object
      lodash: {
        commonjs: 'lodash',
        amd: 'lodash',
        root: '_', // indicates global variable
      },
      // [string]
      subtract: ['./math', 'subtract'],
    },
    // Function
    function ({ context, request }, callback) {
      if (/^yourregex$/.test(request)) {
        return callback(null, 'commonjs ' + request);
      }
      callback();
    },
    // Regex
    /^(jquery|\$)$/i,
  ],
};

如需如何使用此組態的更多資訊,請參閱有關 如何撰寫函式庫 的文章。

byLayer

function object

依據層級指定外部函式庫。

webpack.config.js

module.exports = {
  externals: {
    byLayer: {
      layer: {
        external1: 'var 43',
      },
    },
  },
};

externalsType

字串 = 'var'

指定外部函式庫的預設類型。amdumdsystemjsonp 外部函式庫取決於 output.libraryTarget 設定為相同的值,例如,你只能在 amd 函式庫中使用 amd 外部函式庫。

支援的類型

webpack.config.js

module.exports = {
  //...
  externalsType: 'promise',
};

externalsType.commonjs

將外部函式庫的預設類型指定為 'commonjs'。Webpack 會為模組中使用的外部函式庫產生類似 const X = require('...') 的程式碼。

範例

import fs from 'fs-extra';

webpack.config.js

module.exports = {
  // ...
  externalsType: 'commonjs',
  externals: {
    'fs-extra': 'fs-extra',
  },
};

將產生類似以下的內容

const fs = require('fs-extra');

請注意,輸出套件中將會有一個 require()

externalsType.global

將外部函式庫的預設類型指定為 'global'。Webpack 會在 globalObject 上將外部函式庫讀取為全域變數。

範例

import jq from 'jquery';
jq('.my-element').animate(/* ... */);

webpack.config.js

module.exports = {
  // ...
  externalsType: 'global',
  externals: {
    jquery: '$',
  },
  output: {
    globalObject: 'global',
  },
};

將產生類似以下的內容

const jq = global['$'];
jq('.my-element').animate(/* ... */);

externalsType.module

指定 externals 的預設類型為 'module'。Webpack 將會為模組中使用的 externals 產生類似 import * as X from '...' 的程式碼。

請務必先啟用 experiments.outputModule,否則 webpack 將會擲回錯誤。

範例

import jq from 'jquery';
jq('.my-element').animate(/* ... */);

webpack.config.js

module.exports = {
  experiments: {
    outputModule: true,
  },
  externalsType: 'module',
  externals: {
    jquery: 'jquery',
  },
};

將產生類似以下的內容

import * as __WEBPACK_EXTERNAL_MODULE_jquery__ from 'jquery';

const jq = __WEBPACK_EXTERNAL_MODULE_jquery__['default'];
jq('.my-element').animate(/* ... */);

請注意輸出套件中將會有一個 import 陳述式。

externalsType.node-commonjs

指定 externals 的預設類型為 'node-commonjs'。Webpack 將會從 'module' 匯入 createRequire 來建構一個 require 函式,用於載入模組中使用的 externals。

範例

import jq from 'jquery';
jq('.my-element').animate(/* ... */);

webpack.config.js

module.export = {
  experiments: {
    outputModule: true,
  },
  externalsType: 'node-commonjs',
  externals: {
    jquery: 'jquery',
  },
};

將產生類似以下的內容

import { createRequire } from 'module';

const jq = createRequire(import.meta.url)('jquery');
jq('.my-element').animate(/* ... */);

請注意輸出套件中將會有一個 import 陳述式。

externalsType.promise

指定 externals 的預設類型為 'promise'。Webpack 將會將 external 視為一個全域變數(類似於 'var'),並對其進行 await

範例

import jq from 'jquery';
jq('.my-element').animate(/* ... */);

webpack.config.js

module.exports = {
  // ...
  externalsType: 'promise',
  externals: {
    jquery: '$',
  },
};

將產生類似以下的內容

const jq = await $;
jq('.my-element').animate(/* ... */);

externalsType.self

指定 externals 的預設類型為 'self'。Webpack 將會將 external 視為 self 物件上的全域變數。

範例

import jq from 'jquery';
jq('.my-element').animate(/* ... */);

webpack.config.js

module.exports = {
  // ...
  externalsType: 'self',
  externals: {
    jquery: '$',
  },
};

將產生類似以下的內容

const jq = self['$'];
jq('.my-element').animate(/* ... */);

externalsType.script

將外部程式碼的預設類型指定為 'script'。Webpack 會將外部程式碼載入為腳本,並透過 HTML <script> 元素公開預先定義的全球變數。<script> 標籤會在腳本載入後移除。

語法

module.exports = {
  externalsType: 'script',
  externals: {
    packageName: [
      'http://example.com/script.js',
      'global',
      'property',
      'property',
    ], // properties are optional
  },
};

如果您不打算指定任何屬性,也可以使用捷徑語法

module.exports = {
  externalsType: 'script',
  externals: {
    packageName: 'global@http://example.com/script.js', // no properties here
  },
};

請注意,output.publicPath 不會新增到提供的 URL。

範例

讓我們從 CDN 載入 lodash

webpack.config.js

module.exports = {
  // ...
  externalsType: 'script',
  externals: {
    lodash: ['https://cdn.jsdelivr.net/npm/lodash@4.17.19/lodash.min.js', '_'],
  },
};

然後在程式碼中使用它

import _ from 'lodash';
console.log(_.head([1, 2, 3]));

以下是我們如何為上述範例指定屬性的方式

module.exports = {
  // ...
  externalsType: 'script',
  externals: {
    lodash: [
      'https://cdn.jsdelivr.net/npm/lodash@4.17.19/lodash.min.js',
      '_',
      'head',
    ],
  },
};

當您 import lodash 時,本機變數 head 和全域變數 window._ 都會公開

import head from 'lodash';
console.log(head([1, 2, 3])); // logs 1 here
console.log(window._.head(['a', 'b'])); // logs a here

externalsType.this

將外部程式碼的預設類型指定為 'this'。Webpack 會將外部程式碼讀取為 this 物件上的全域變數。

範例

import jq from 'jquery';
jq('.my-element').animate(/* ... */);

webpack.config.js

module.exports = {
  // ...
  externalsType: 'this',
  externals: {
    jquery: '$',
  },
};

將產生類似以下的內容

const jq = this['$'];
jq('.my-element').animate(/* ... */);

externalsType.var

將 externals 的預設類型指定為 'var'。Webpack 會將 external 讀取為全域變數。

範例

import jq from 'jquery';
jq('.my-element').animate(/* ... */);

webpack.config.js

module.exports = {
  // ...
  externalsType: 'var',
  externals: {
    jquery: '$',
  },
};

將產生類似以下的內容

const jq = $;
jq('.my-element').animate(/* ... */);

externalsType.window

將 externals 的預設類型指定為 'window'。Webpack 會將 external 讀取為 window 物件上的全域變數。

範例

import jq from 'jquery';
jq('.my-element').animate(/* ... */);

webpack.config.js

module.exports = {
  // ...
  externalsType: 'window',
  externals: {
    jquery: '$',
  },
};

將產生類似以下的內容

const jq = window['$'];
jq('.my-element').animate(/* ... */);

externalsPresets

物件

針對特定目標啟用 externals 的預設值。

選項說明輸入類型
electron將主程式和預載入內容中常見的 electron 內建模組(例如 electronipcshell)視為 external,並在使用時透過 require() 載入。布林值
electronMain將主程式內容中的 electron 內建模組(例如 appipc-mainshell)視為 external,並在使用時透過 require() 載入。布林值
electronPreload將預載入內容中的 electron 內建模組(例如 web-frameipc-renderershell)視為 external,並在使用時透過 require() 載入。布林值
electronRenderer將呈現器內容中的 electron 內建模組(例如 web-frameipc-renderershell)視為 external,並在使用時透過 require() 載入。布林值
node將 node.js 內建模組(例如 fspathvm)視為 external,並在使用時透過 require() 載入。布林值
nwjsNW.js 舊版 nw.gui 模組視為外部模組,並在使用時透過 require() 載入。布林值
web將對 http(s)://...std:... 的參照視為外部參照,並在使用時透過 import 載入。(請注意,這會變更執行順序,因為外部程式碼會在區塊中的任何其他程式碼之前執行)布林值
webAsync將對 http(s)://...std:... 的參照視為外部參照,並在使用時透過 async import() 載入。(請注意,此外部類型是一個 async 模組,這會對執行產生各種影響)布林值

請注意,如果您要使用這些與 node.js 相關的預設值來輸出 ES 模組,webpack 會將預設的 externalsType 設定為 node-commonjs,它會使用 createRequire 來建構一個 require 函式,而不是使用 require()

範例

使用 node 預設值不會將內建模組打包,並將它們視為外部模組,並在使用時透過 require() 載入。

webpack.config.js

module.exports = {
  // ...
  externalsPresets: {
    node: true,
  },
};

17 貢獻者

sokraskipjackpksjcefadysamirsadekbyzykzefmanMistyyyyjamesgeorge007tanhauhausnitin315beejunkEugeneHlushkochenxsanpranshuchittorakinetifexanshumanvSaulSilver