externals 配置選項(xiàng)提供了「從輸出的 bundle 中排除依賴」的方法。相反,所創(chuàng)建的 bundle 依賴于那些存在于用戶環(huán)境(consumer's environment)中的依賴。此功能通常對(duì) library 開發(fā)人員來(lái)說(shuō)是最有用的,然而也會(huì)有各種各樣的應(yīng)用程序用到它。
string object function RegExp [string, object, function, RegExp]
防止將某些 import 的包(package)打包到 bundle 中,而是在運(yùn)行時(shí)(runtime)再去從外部獲取這些擴(kuò)展依賴(external dependencies)。
例如,從 CDN 引入 jQuery,而不是把它打包:
index.html
<script
src="https://code.jquery.com/jquery-3.1.0.js" rel="external nofollow"
integrity="sha256-slogkvB1K3VOkzAI8QITxV3VzpOnkeNVsKvtkYLMjfk="
crossorigin="anonymous"
></script>
webpack.config.js
module.exports = {
//...
externals: {
jquery: 'jQuery',
},
};
這樣就剝離了那些不需要改動(dòng)的依賴模塊,換句話,下面展示的代碼還可以正常運(yùn)行:
import $ from 'jquery';
$('.my-element').animate(/* ... */);
上面 webpack.config.js 中 externals 下指定的屬性名稱 jquery 表示 import $ from 'jquery' 中的模塊 jquery 應(yīng)該從打包產(chǎn)物中排除。 為了替換這個(gè)模塊,jQuery 值將用于檢索全局 jQuery 變量,因?yàn)槟J(rèn)的外部庫(kù)類型是 var,請(qǐng)參閱 externalsType。
雖然我們?cè)谏厦嬲故玖艘粋€(gè)使用外部全局變量的示例,但實(shí)際上可以以以下任何形式使用外部變量:全局變量、CommonJS、AMD、ES2015 模塊,在 externalsType 中查看更多信息。
根據(jù) externalsType,這可能是全局變量的名稱(參見 'global'、'this'、 'var ', 'window') 或模塊的名稱(參見 amd, commonjs, module, umd)。
如果你只定義 1 個(gè) external,您也可以使用快捷語(yǔ)法:
module.exports = {
//...
externals: 'jquery',
};
equals to
module.exports = {
//...
externals: {
jquery: 'jquery',
},
};
您可以使用 ${externalsType} ${libraryName} 語(yǔ)法為外部指定 外部庫(kù)類型。 它將覆蓋 externalsType 選項(xiàng)中指定的默認(rèn)外部庫(kù)類型。
例如,如果外部庫(kù)是一個(gè) CommonJS 模塊,你可以指定
module.exports = {
//...
externals: {
jquery: 'commonjs jquery',
},
};
module.exports = {
//...
externals: {
subtract: ['./math', 'subtract'],
},
};
?subtract: ['./math', 'subtract']
? 允許你選擇模塊的一部分,其中 ?./math
? 是模塊,并且你的包只需要 subtract 變量下的子集。
當(dāng) externalsType 為 commonjs 時(shí),此示例將轉(zhuǎn)換為 ?require('./math').subtract;
?,而當(dāng) externalsType 為 window 時(shí),此示例將轉(zhuǎn)換為 ?window["./math"]["subtract"];
?
與 string 語(yǔ)法 類似,你可以使用 ${externalsType} ${libraryName} 語(yǔ)法在數(shù)組的第一項(xiàng)中指定外部庫(kù)類型,例如:
module.exports = {
//...
externals: {
subtract: ['commonjs ./math', 'subtract'],
},
};
module.exports = {
//...
externals: {
react: 'react',
},
// 或者
externals: {
lodash: {
commonjs: 'lodash',
amd: 'lodash',
root: '_', // 指向全局變量
},
},
// 或者
externals: {
subtract: {
root: ['math', 'subtract'],
},
},
};
此語(yǔ)法用于描述外部 library 所有可用的訪問(wèn)方式。這里 lodash 這個(gè)外部 library 可以在 AMD 和 CommonJS 模塊系統(tǒng)中通過(guò) lodash 訪問(wèn),但在全局變量形式下用 _ 訪問(wèn)。subtract 可以通過(guò)全局 math 對(duì)象下的屬性 subtract 訪問(wèn)(例如 window['math']['subtract'])。
function ({ context, request, contextInfo, getResolve }, callback)
?function ({ context, request, contextInfo, getResolve }) => promise
? 5.15.0+
對(duì)于 webpack 外部化,通過(guò)定義函數(shù)來(lái)控制行為,可能會(huì)很有幫助。例如,webpack-node-externals 能夠排除 node_modules 目錄中所有模塊,還提供一些選項(xiàng),比如白名單 package(whitelist package)。
函數(shù)接收兩個(gè)入?yún)ⅲ?/p>
回調(diào)函數(shù)接收三個(gè)入?yún)ⅲ?/p>
作為例子,要外部化所有匹配一個(gè)正則表達(dá)式的引入,你可以像下面那樣處理:
webpack.config.js
module.exports = {
//...
externals: [
function ({ context, request }, callback) {
if (/^yourregex$/.test(request)) {
// 使用 request 路徑,將一個(gè) commonjs 模塊外部化
return callback(null, 'commonjs ' + request);
}
// 繼續(xù)下一步且不外部化引用
callback();
},
],
};
其它例子使用不同的模塊格式:
webpack.config.js
module.exports = {
externals: [
function (ctx, callback) {
// 該外部化的模塊,是一個(gè) `commonjs2` 的模塊,且放在 `@scope/library` 目錄中
callback(null, '@scope/library', 'commonjs2');
},
],
};
webpack.config.js
module.exports = {
externals: [
function (ctx, callback) {
// 該外部化模塊是一個(gè)全局變量叫作 `nameOfGlobal`.
callback(null, 'nameOfGlobal');
},
],
};
webpack.config.js
module.exports = {
externals: [
function (ctx, callback) {
// 該外部化模塊是一個(gè)在`@scope/library`模塊里的命名導(dǎo)出(named export)。
callback(null, ['@scope/library', 'namedexport'], 'commonjs');
},
],
};
webpack.config.js
module.exports = {
externals: [
function (ctx, callback) {
// 外部化模塊是一個(gè) UMD 模塊
callback(null, {
root: 'componentsGlobal',
commonjs: '@scope/components',
commonjs2: '@scope/components',
amd: 'components',
});
},
],
};
匹配給定正則表達(dá)式的每個(gè)依賴,都將從輸出 bundle 中排除。
webpack.config.js
module.exports = {
//...
externals: /^(jquery|\$)$/i,
};
這個(gè)示例中,所有名為 jQuery 的依賴(忽略大小寫),或者 $,都會(huì)被外部化。
有時(shí)你需要混用上面介紹的語(yǔ)法。這可以像以下這樣操作:
webpack.config.js
module.exports = {
//...
externals: [
{
// 字符串
react: 'react',
// 對(duì)象
lodash: {
commonjs: 'lodash',
amd: 'lodash',
root: '_', // indicates global variable
},
// 字符串?dāng)?shù)組
subtract: ['./math', 'subtract'],
},
// 函數(shù)
function ({ context, request }, callback) {
if (/^yourregex$/.test(request)) {
return callback(null, 'commonjs ' + request);
}
callback();
},
// 正則表達(dá)式
/^(jquery|\$)$/i,
],
};
?function object
?
按層指定 externals:
webpack.config.js
module.exports = {
externals: {
byLayer: {
layer: {
external1: 'var 43',
},
},
},
};
?string = 'var'
?
指定 externals 的默認(rèn)類型。當(dāng) external 被設(shè)置為 amd,umd,system 以及 jsonp 時(shí),output.libraryTarget 的值也應(yīng)相同。例如,你只能在 amd 庫(kù)中使用 amd 的 externals。
支持的類型如下:
'amd'
?'amd-require'
?'assign'
? - same as 'var''commonjs'
?'commonjs-module'
?'global'
?'import'
? - uses import() to load a native EcmaScript module (async module)'jsonp'
?'module'
?'node-commonjs'
?'promise'
? - 與 'var' 相同,但是會(huì) await 結(jié)果(適用于 async 模塊)'self'
?'system'
?'script'
?'this'
?'umd'
?'umd2'
?'var'
?'window'
?webpack.config.js
module.exports = {
//...
externalsType: 'promise',
};
將外部的默認(rèn)類型指定為“commonjs”。Webpack 將為模塊中使用的外部生成類似 const X = require('...') 的代碼。
import fs from 'fs-extra';
webpack.config.js
module.exports = {
// ...
externalsType: 'commonjs',
externals: {
'fs-extra': 'fs-extra',
},
};
將會(huì)轉(zhuǎn)換為類似下面的代碼:
const fs = require('fs-extra');
請(qǐng)注意,輸出產(chǎn)物中會(huì)有一個(gè) require()。
將外部的默認(rèn)類型指定為 'global'。Webpack 會(huì)將 external 作為全局變量讀取到 globalObject。
import jq from 'jquery';
jq('.my-element').animate(/* ... */);
webpack.config.js
module.exports = {
// ...
externalsType: 'global',
externals: {
jquery: '$',
},
output: {
globalObject: 'global',
},
};
將會(huì)轉(zhuǎn)換為類似下面的代碼:
const jq = global['$'];
jq('.my-element').animate(/* ... */);
將 externals 類型設(shè)置為 'module',webpack 將會(huì)在 module 中為外部引用生成形如 import * as X from '...' 的代碼。
確保首先把 experiments.outputModule 設(shè)置為 true, 否則 webpack 將會(huì)報(bào)錯(cuò)。
import jq from 'jquery';
jq('.my-element').animate(/* ... */);
webpack.config.js
module.exports = {
experiments: {
outputModule: true,
},
externalsType: 'module',
externals: {
jquery: 'jquery',
},
};
將會(huì)轉(zhuǎn)換為類似下面的代碼:
import * as __WEBPACK_EXTERNAL_MODULE_jquery__ from 'jquery';
const jq = __WEBPACK_EXTERNAL_MODULE_jquery__['default'];
jq('.my-element').animate(/* ... */);
請(qǐng)注意,輸出產(chǎn)物中會(huì)有一個(gè) import 語(yǔ)句。
將 externals 類型設(shè)置為 'node-commonjs',webpack 將從 module 中導(dǎo)入 createRequire 來(lái)構(gòu)造一個(gè) require 函數(shù),用于加載模塊中使用的外部對(duì)象。
import jq from 'jquery';
jq('.my-element').animate(/* ... */);
webpack.config.js
module.export = {
experiments: {
outputModule: true,
},
externalsType: 'node-commonjs',
externals: {
jquery: 'jquery',
},
};
將會(huì)轉(zhuǎn)換為類似下面的代碼:
import { createRequire } from 'module';
const jq = createRequire(import.meta.url)('jquery');
jq('.my-element').animate(/* ... */);
請(qǐng)注意,輸出包中會(huì)有一個(gè) import 語(yǔ)句。
將外部的默認(rèn)類型指定為 'promise'。Webpack 會(huì)將 external 讀取為全局變量(類似于 'var')并為它執(zhí)行 await。
import jq from 'jquery';
jq('.my-element').animate(/* ... */);
webpack.config.js
module.exports = {
// ...
externalsType: 'promise',
externals: {
jquery: '$',
},
};
將會(huì)轉(zhuǎn)換為類似下面的代碼:
const jq = await $;
jq('.my-element').animate(/* ... */);
將外部的默認(rèn)類型指定為 'self'。 Webpack 會(huì)將 external 作為 self 對(duì)象上的全局變量讀取。
import jq from 'jquery';
jq('.my-element').animate(/* ... */);
webpack.config.js
module.exports = {
// ...
externalsType: 'self',
externals: {
jquery: '$',
},
};
將會(huì)轉(zhuǎn)換為類似下面的代碼:
const jq = self['$'];
jq('.my-element').animate(/* ... */);
將 external 的默認(rèn)類型指定為 'script'。Webpack 會(huì)將 external 作為腳本加載,并使用 HTML <script> 元素暴露預(yù)定義的全局變量。<script> 標(biāo)簽將在腳本加載后被移除。
module.exports = {
externalsType: 'script',
externals: {
packageName: [
'http://example.com/script.js',
'global',
'property',
'property',
], // properties are optional
},
};
如果你不打算定義任何屬性,你可以使用簡(jiǎn)寫形式:
module.exports = {
externalsType: 'script',
externals: {
packageName: 'global@http://example.com/script.js', // no properties here
},
};
請(qǐng)注意,output.publicPath 不會(huì)被添加到提供的 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]));
下面示例是針對(duì)上面示例新增了屬性配置:
module.exports = {
// ...
externalsType: 'script',
externals: {
lodash: [
'https://cdn.jsdelivr.net/npm/lodash@4.17.19/lodash.min.js',
'_',
'head',
],
},
};
當(dāng)你 import 'loadsh' 時(shí),局部變量 head 和全局變量 window._ 都會(huì)被暴露:
import head from 'lodash';
console.log(head([1, 2, 3])); // logs 1 here
console.log(window._.head(['a', 'b'])); // logs a here
將 external 的默認(rèn)類型指定為 'this'。Webpack 會(huì)將 external 作為 this 對(duì)象上的全局變量讀取。
示例:
import jq from 'jquery';
jq('.my-element').animate(/* ... */);
webpack.config.js
module.exports = {
// ...
externalsType: 'this',
externals: {
jquery: '$',
},
};
將會(huì)轉(zhuǎn)換為類似下面的代碼:
const jq = this['$'];
jq('.my-element').animate(/* ... */);
將 external 的默認(rèn)類型指定為 'var'。Webpack 會(huì)將 external 作為全局變量讀取。
示例:
import jq from 'jquery';
jq('.my-element').animate(/* ... */);
webpack.config.js
module.exports = {
// ...
externalsType: 'var',
externals: {
jquery: '$',
},
};
將會(huì)轉(zhuǎn)換為類似下面的代碼:
const jq = $;
jq('.my-element').animate(/* ... */);
將 external 的默認(rèn)類型指定為 'window'。Webpack 會(huì)將 external 作為 window 對(duì)象上的全局變量讀取。
示例:
import jq from 'jquery';
jq('.my-element').animate(/* ... */);
webpack.config.js
module.exports = {
// ...
externalsType: 'window',
externals: {
jquery: '$',
},
};
將會(huì)轉(zhuǎn)換為類似下面的代碼:
const jq = window['$'];
jq('.my-element').animate(/* ... */);
?object
?
為特定的 target 啟用 externals 的 preset。
選項(xiàng) | 描述 | 輸入類型 |
---|---|---|
electron
|
將 main 和預(yù)加載上下文中常見的 electron 內(nèi)置模塊視為 external 模塊(如 electron ,ipc 或 shell ),使用時(shí)通過(guò) require() 加載。 |
boolean |
electronMain
|
將 main 上下文中的 electron 內(nèi)置模塊視為 external 模塊(如 app ,ipc-main 或 shell ),使用時(shí)通過(guò) require() 加載。 |
boolean |
electronPreload
|
將預(yù)加載上下文的 electron 內(nèi)置模塊視為 external 模塊(如 web-frame ,ipc-renderer 或 shell ),使用時(shí)通過(guò) require() 加載。 |
boolean |
electronRenderer
|
將 renderer 上下文的 electron 內(nèi)置模塊視為 external 模塊(如 web-frame 、ipc-renderer 或 shell ),使用時(shí)通過(guò) require() 加載。 |
boolean |
node
|
將 node.js 的內(nèi)置模塊視為 external 模塊(如 fs ,path 或 vm ),使用時(shí)通過(guò) require() 加載。 |
boolean |
nwjs
|
將 NW.js 遺留的 nw.gui 模塊視為 external 模塊,使用時(shí)通過(guò) require() 加載。 |
boolean |
web
|
將 http(s)://... 以及 std:... 視為 external 模塊,使用時(shí)通過(guò) import 加載。(注意,這將改變執(zhí)行順序,因?yàn)?external 代碼會(huì)在該塊中的其他代碼執(zhí)行前被執(zhí)行)。 |
boolean |
webAsync
|
將 'http(s)://...' 以及 'std:...' 的引用視為 external 模塊,使用時(shí)通過(guò) async import() 加載。(注意,此 external 類型為 async 模塊,它對(duì)執(zhí)行會(huì)產(chǎn)生各種副作用)。 |
boolean |
請(qǐng)注意,如果打算使用與Node.js相關(guān)的預(yù)設(shè)輸出ES模塊,Webpack將會(huì)將默認(rèn)的externalsType設(shè)置為node-commonjs,這將使用createRequire來(lái)構(gòu)建一個(gè)require函數(shù),而不是使用require()函數(shù)。
示例:
使用 node 的 preset 不會(huì)構(gòu)建內(nèi)置模塊,而會(huì)將其視為 external 模塊,使用時(shí)通過(guò) require() 加載。
webpack.config.js
module.exports = {
// ...
externalsPresets: {
node: true,
},
};
更多建議: