CC 4.0 授權條款

本節內容衍生自以下連結的內容,並受 CC BY 4.0 授權條款約束。

若未特別聲明,以下內容可視為基於原始內容進行修改和刪除的結果。

外部函式庫

externals 設定選項提供了一種從輸出捆綁包中排除依賴項的方法。相反,建立的捆綁包依賴於該依賴項存在於消費者(任何最終使用者應用程式)的環境中。此功能通常對函式庫開發人員最有用,但它也有各種應用。

externals

  • 類型: string | object | function | RegExp | Array<string | object | function | RegExp>

防止捆綁某些 import 的套件,而是在執行時檢索這些外部依賴項

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

index.html

<script
  src="https://code.jquery.com/jquery-3.1.0.js"
  integrity="sha256-slogkvB1K3VOkzAI8QITxV3VzpOnkeNVsKvtkYLMjfk="
  crossorigin="anonymous"
></script>
rspack.config.js
module.exports = {
  //...
  externals: {
    jquery: 'jQuery',
  },
};

這會使任何依賴模組保持不變,即下面顯示的程式碼仍然可以工作

import $ from 'jquery';

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

在上面的 rspack.config.js 中,在 externals 下指定的屬性名稱 jquery 表示 import $ from 'jquery' 中的模組 jquery 應排除在捆綁之外。為了替換此模組,將使用值 jQuery 來檢索全域 jQuery 變數,因為預設的外部函式庫類型為 var,請參閱 externalsType

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

字串

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

如果您只定義一個外部模組,也可以使用簡寫語法。

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

等於

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

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

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

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

string[]

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

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

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

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

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

object

警告

具有 { root, amd, commonjs, ... } 的物件僅適用於 libraryTarget: 'umd'externalsType: 'umd'。它不適用於其他函式庫目標。

rspack.config.js
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

  • 類型
    • function ({ context, request, contextInfo, getResolve }, callback)
    • function ({ context, request, contextInfo, getResolve }) => promise

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

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

  • ctx (object):包含檔案詳細資訊的物件。
    • ctx.context (string):包含 import 的檔案目錄。
    • ctx.request (string):正在請求的 import 路徑。
    • ctx.contextInfo (object):包含關於發出者的資訊(例如圖層和編譯器)。
    • ctx.getResolve:使用目前的解析器選項取得解析函式。
  • callback (function (err, result, type)):回呼函式,用於指示模組應該如何外部化。

回呼函式接受三個參數

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

作為範例,若要外部化 import 路徑與正規表達式相符的所有 import,您可以執行以下操作

rspack.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();
    },
  ],
};

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

rspack.config.js
module.exports = {
  externals: [
    function (ctx, callback) {
      // The external is a `commonjs2` module located in `@scope/library`
      callback(null, '@scope/library', 'commonjs2');
    },
  ],
};
rspack.config.js
module.exports = {
  externals: [
    function (ctx, callback) {
      // The external is a global variable called `nameOfGlobal`.
      callback(null, 'nameOfGlobal');
    },
  ],
};
rspack.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');
    },
  ],
};
rspack.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

每個符合給定正規表達式的相依性都將從輸出捆綁包中排除。

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

在這種情況下,任何名為 jQuery(無論是否大寫)或 $ 的相依性都將被外部化。

組合語法

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

rspack.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,
  ],
};
警告

如果您在沒有類型的情況下指定 externals,則會使用預設類型,例如 externals: { react: 'react' } 而不是 externals: { react: 'commonjs-module react' }

externalsType

  • 類型: string
  • 預設值: 'var'

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

支援的類型

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

externalsType.commonjs

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

範例

import fs from 'fs-extra';
rspack.config.js
module.exports = {
  // ...
  externalsType: 'commonjs',
  externals: {
    'fs-extra': 'fs-extra',
  },
};

將會產生類似以下的程式碼

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

請注意,輸出捆綁包中會有 require()

externalsType.global

將外部模組的預設類型指定為 'global'。Rspack 會在 globalObject 上將外部模組讀取為全域變數。

範例

import jq from 'jquery';
jq('.my-element').animate(/* ... */);
rspack.config.js
module.exports = {
  // ...
  externalsType: 'global',
  externals: {
    jquery: '$',
  },
  output: {
    globalObject: 'global',
  },
};

將會產生類似以下的程式碼

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

externalsType.module

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

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

範例

import jq from 'jquery';
jq('.my-element').animate(/* ... */);
rspack.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.import

將外部模組的預設類型指定為 'import'。Rspack 會為模組中使用的外部模組產生類似 import('...') 的程式碼。

範例

async function foo() {
  const jq = await import('jQuery');
  jq('.my-element').animate(/* ... */);
}
rspack.config.js
module.exports = {
  externalsType: 'import',
  externals: {
    jquery: 'jquery',
  },
};

將會產生類似以下的程式碼

var __webpack_modules__ = {
  jQuery: module => {
    module.exports = import('jQuery');
  },
};

// webpack runtime...

async function foo() {
  const jq = await Promise.resolve(/* import() */).then(
    __webpack_require__.bind(__webpack_require__, 'jQuery'),
  );
  jq('.my-element').animate(/* ... */);
}

請注意,輸出捆綁包中會有 import() 陳述式。

externalsType['module-import']

將外部模組的預設類型指定為 'module-import'。這會結合 'module''import'。Rspack 會自動偵測 import 語法的類型,將靜態 import 設定為 'module',將動態 import 設定為 'import'

如果存在靜態 import,請務必先啟用 experiments.outputModule,否則 Rspack 會擲回錯誤。

範例

import { attempt } from 'lodash';

async function foo() {
  const jq = await import('jQuery');
  attempt(() => jq('.my-element').animate(/* ... */));
}
rspack.config.js
module.exports = {
  externalsType: 'import',
  externals: {
    jquery: 'jquery',
  },
};

將會產生類似以下的程式碼

import * as __WEBPACK_EXTERNAL_MODULE_lodash__ from 'lodash';
const lodash = __WEBPACK_EXTERNAL_MODULE_jquery__;

var __webpack_modules__ = {
  jQuery: module => {
    module.exports = import('jQuery');
  },
};

// webpack runtime...

async function foo() {
  const jq = await Promise.resolve(/* import() */).then(
    __webpack_require__.bind(__webpack_require__, 'jQuery'),
  );
  (0, lodash.attempt)(() => jq('.my-element').animate(/* ... */));
}

請注意,輸出捆綁包中會有 importimport() 陳述式。

當模組不是透過 importimport() 匯入時,Rspack 會使用 "module" 外部模組類型作為後備方案。如果您想要使用不同的外部模組類型作為後備方案,您可以使用 externals 選項中的函式來指定。例如

rspack.config.js
module.exports = {
  externalsType: "module-import",
  externals: [
    function (
      { request, dependencyType },
      callback
    ) {
      if (dependencyType === "commonjs") {
        return callback(null, `node-commonjs ${request}`);
      }
      callback();
    },
  ]

externalsType['node-commonjs']

將外部模組的預設類型指定為 'node-commonjs'。Rspack 會從 'module' 匯入 createRequire,以建構用於載入模組中使用的外部模組的 require 函式。

範例

import jq from 'jquery';
jq('.my-element').animate(/* ... */);
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

將外部模組的預設類型指定為 'promise'。Rspack 會將外部模組讀取為全域變數(類似於 'var')並 await 其結果。

範例

import jq from 'jquery';
jq('.my-element').animate(/* ... */);
rspack.config.js
module.exports = {
  // ...
  externalsType: 'promise',
  externals: {
    jquery: '$',
  },
};

將會產生類似以下的程式碼

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

externalsType.self

將外部模組的預設類型指定為 'self'。Rspack 會在 self 物件上將外部模組讀取為全域變數。

範例

import jq from 'jquery';
jq('.my-element').animate(/* ... */);
rspack.config.js
module.exports = {
  // ...
  externalsType: 'self',
  externals: {
    jquery: '$',
  },
};

將會產生類似以下的程式碼

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

externalsType.script

將外部模組的預設類型指定為 'script'。Rspack 會使用 HTML <script> 元素將外部模組載入為公開預定義全域變數的指令碼。指令碼載入後,會移除 <script> 標籤。

語法

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

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

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

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

範例

讓我們從 CDN 載入 lodash

rspack.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]));

以下是如何為上述範例指定屬性

rspack.config.js
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
提示

使用 HTML <script> 標籤載入程式碼時,Rspack 執行階段會嘗試尋找符合 src 屬性或具有特定 data-webpack 屬性的現有 <script> 標籤。對於區塊載入,data-webpack 屬性的值將為 '[output.uniqueName]:chunk-[chunkId]',而外部指令碼的值則為 '[output.uniqueName]:[global]'

諸如 output.chunkLoadTimeoutoutput.crossOriginLoadingoutput.scriptType 等選項也會對以此方式載入的外部腳本產生影響。

externalsType.this

將外部模組的預設類型指定為 'this'。Rspack 會將外部模組讀取為 this 物件上的全域變數。

範例

import jq from 'jquery';
jq('.my-element').animate(/* ... */);
rspack.config.js
module.exports = {
  // ...
  externalsType: 'this',
  externals: {
    jquery: '$',
  },
};

將會產生類似以下的程式碼

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

externalsType.var

將外部模組的預設類型指定為 'var'。Rspack 會將外部模組讀取為全域變數。

範例

import jq from 'jquery';
jq('.my-element').animate(/* ... */);
rspack.config.js
module.exports = {
  // ...
  externalsType: 'var',
  externals: {
    jquery: '$',
  },
};

將會產生類似以下的程式碼

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

externalsType.window

將外部模組的預設類型指定為 'window'。Rspack 會將外部模組讀取為 window 物件上的全域變數。

範例

import jq from 'jquery';
jq('.my-element').animate(/* ... */);
rspack.config.js
module.exports = {
  // ...
  externalsType: 'window',
  externals: {
    jquery: '$',
  },
};

將會產生類似以下的程式碼

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

externalsPresets

  • 類型: object

為特定目標啟用外部模組的預設設定。

externalsPresets.electron

類型: boolean

將主程式和預載環境中常見的 Electron 內建模組(例如 electronipcshell)視為外部模組,並在使用時透過 require() 載入。

externalsPresets.electronMain

類型: boolean

將主程式環境中的 Electron 內建模組(例如 appipc-mainshell)視為外部模組,並在使用時透過 require() 載入。

externalsPresets.electronPreload

類型: boolean

將預載環境中的 Electron 內建模組(例如 web-frameipc-renderershell)視為外部模組,並在使用時透過 require() 載入。

externalsPresets.electronRenderer

類型: boolean

將渲染器環境中的 Electron 內建模組(例如 web-frameipc-renderershell)視為外部模組,並在使用時透過 require() 載入。

externalsPresets.node

類型: boolean

將 Node.js 內建模組(例如 fspathvm)視為外部模組,並在使用時透過 require() 載入。

externalsPresets.nwjs

類型: boolean

NW.js 舊版的 nw.gui 模組視為外部模組,並在使用時透過 require() 載入。

externalsPresets.web

類型: boolean

將對 http(s)://...std:... 的引用視為外部模組,並在使用時透過 import 載入。(請注意,這會變更執行順序,因為外部模組會在區塊中的任何其他程式碼之前執行)

externalsPresets.webAsync

類型: boolean

將對 http(s)://...std:... 的引用視為外部模組,並在使用時透過 async import() 載入 (請注意,此外部模組類型為 async 模組,其對執行有各種影響)

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

範例

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

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