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'
)或是模組的名稱(請參閱 amd
、commonjs
、module
、umd
)。
如果您只定義一個外部模組,也可以使用簡寫語法。
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
變數下的子集。
當 externalsType
為 commonjs
時,此範例會轉換為 require('./math').subtract;
,而當 externalsType
為 window
時,此範例會轉換為 window["./math"]["subtract"];
類似於 字串語法,您可以使用 ${externalsType} ${libraryName}
語法在陣列的第一個項目中指定外部函式庫類型,例如
rspack.config.js
module.exports = {
//...
externals: {
subtract: ['commonjs ./math', 'subtract'],
},
};
object
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
):使用其他外部格式(string
、string[]
或 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
指定外部模組的預設類型。amd
、umd
、system
和 jsonp
外部模組取決於 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(/* ... */));
}
請注意,輸出捆綁包中會有 import
或 import()
陳述式。
當模組不是透過 import
或 import()
匯入時,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.chunkLoadTimeout
、output.crossOriginLoading
和 output.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
為特定目標啟用外部模組的預設設定。
externalsPresets.electron
類型: boolean
將主程式和預載環境中常見的 Electron 內建模組(例如 electron
、ipc
或 shell
)視為外部模組,並在使用時透過 require()
載入。
externalsPresets.electronMain
類型: boolean
將主程式環境中的 Electron 內建模組(例如 app
、ipc-main
或 shell
)視為外部模組,並在使用時透過 require()
載入。
externalsPresets.electronPreload
類型: boolean
將預載環境中的 Electron 內建模組(例如 web-frame
、ipc-renderer
或 shell
)視為外部模組,並在使用時透過 require()
載入。
externalsPresets.electronRenderer
類型: boolean
將渲染器環境中的 Electron 內建模組(例如 web-frame
、ipc-renderer
或 shell
)視為外部模組,並在使用時透過 require()
載入。
externalsPresets.node
類型: boolean
將 Node.js 內建模組(例如 fs
、path
或 vm
)視為外部模組,並在使用時透過 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,
},
};