除了應用程式之外,webpack 也可用來綑綁 JavaScript 函式庫。以下指南是針對希望簡化其綑綁策略的函式庫作者而設計。
假設我們正在撰寫一個小型函式庫 webpack-numbers
,讓使用者可以將數字 1 到 5 從數字表示轉換為文字表示,反之亦然,例如 2 轉換為「二」。
基本專案結構如下所示
專案
+ |- webpack.config.js
+ |- package.json
+ |- /src
+ |- index.js
+ |- ref.json
使用 npm 初始化專案,然後安裝 webpack
、webpack-cli
和 lodash
npm init -y
npm install --save-dev webpack webpack-cli lodash
我們將 lodash
安裝為 devDependencies
,而不是 dependencies
,因為我們不希望將其綑綁到我們的函式庫中,否則我們的函式庫很容易會過於龐大。
src/ref.json
[
{
"num": 1,
"word": "One"
},
{
"num": 2,
"word": "Two"
},
{
"num": 3,
"word": "Three"
},
{
"num": 4,
"word": "Four"
},
{
"num": 5,
"word": "Five"
},
{
"num": 0,
"word": "Zero"
}
]
src/index.js
import _ from 'lodash';
import numRef from './ref.json';
export function numToWord(num) {
return _.reduce(
numRef,
(accum, ref) => {
return ref.num === num ? ref.word : accum;
},
''
);
}
export function wordToNum(word) {
return _.reduce(
numRef,
(accum, ref) => {
return ref.word === word && word.toLowerCase() ? ref.num : accum;
},
-1
);
}
讓我們從這個基本的 webpack 設定開始
webpack.config.js
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'webpack-numbers.js',
},
};
在上面的範例中,我們告訴 webpack 將 src/index.js
捆綁到 dist/webpack-numbers.js
。
到目前為止,一切都應該與捆綁應用程式相同,而這裡有不同的部分 - 我們需要透過 output.library
選項公開進入點的匯出。
webpack.config.js
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'webpack-numbers.js',
+ library: "webpackNumbers",
},
};
我們將進入點公開為 webpackNumbers
,以便使用者可以使用腳本標籤使用它
<script src="https://example.org/webpack-numbers.js"></script>
<script>
window.webpackNumbers.wordToNum('Five');
</script>
但是,它僅在透過腳本標籤參照時才有效,無法在其他環境中使用,例如 CommonJS、AMD、Node.js 等。
作為函式庫作者,我們希望它可以在不同的環境中相容,也就是說,使用者應該能夠以以下列出的多種方式使用捆綁的函式庫
CommonJS 模組需要:
const webpackNumbers = require('webpack-numbers');
// ...
webpackNumbers.wordToNum('Two');
AMD 模組需要:
require(['webpackNumbers'], function (webpackNumbers) {
// ...
webpackNumbers.wordToNum('Two');
});
腳本標籤:
<!DOCTYPE html>
<html>
...
<script src="https://example.org/webpack-numbers.js"></script>
<script>
// ...
// Global variable
webpackNumbers.wordToNum('Five');
// Property in the window object
window.webpackNumbers.wordToNum('Five');
// ...
</script>
</html>
讓我們更新 output.library
選項,並將其 type
設定為 'umd'
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'webpack-numbers.js',
- library: 'webpackNumbers',
+ globalObject: 'this',
+ library: {
+ name: 'webpackNumbers',
+ type: 'umd',
+ },
},
};
現在,webpack 將捆綁一個可以與 CommonJS、AMD 和腳本標籤一起使用的函式庫。
現在,如果您執行 npx webpack
,您會發現產生了一個很大的捆綁包。如果您檢查該檔案,您會看到 lodash 已與您的程式碼一起捆綁。在這種情況下,我們希望將 lodash
視為對等相依性。這表示使用者應該已經安裝了 lodash
。因此,您希望放棄對此外部函式庫的控制權,交給函式庫的使用者。
這可以使用 externals
設定檔來完成
webpack.config.js
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'webpack-numbers.js',
library: {
name: "webpackNumbers",
type: "umd"
},
},
+ externals: {
+ lodash: {
+ commonjs: 'lodash',
+ commonjs2: 'lodash',
+ amd: 'lodash',
+ root: '_',
+ },
+ },
};
這表示您的函式庫預期消費者環境中提供一個名為 lodash
的相依性。
對於使用相依性中多個檔案的函式庫
import A from 'library/one';
import B from 'library/two';
// ...
您無法透過在 externals 中指定 library
來將它們從套件中排除。您需要逐一排除或使用正規表示法來排除它們。
module.exports = {
//...
externals: [
'library/one',
'library/two',
// Everything that starts with "library/"
/^library\/.+$/,
],
};
依照 製作指南 中提到的步驟,最佳化您的輸出以進行製作。我們也將您產生的套件路徑新增為 package.json
中套件的 main
欄位
package.json
{
...
"main": "dist/webpack-numbers.js",
...
}
或者,依照 這份指南 將它新增為標準模組
{
...
"module": "src/index.js",
...
}
main
鍵是指 package.json
中的標準,而 module
指的是 一個 提案,允許 JavaScript 生態系統升級以使用 ES2015 模組,而不會中斷向後相容性。
現在您可以將其發布為 npm 套件,並在unpkg.com上找到它,以將其分發給您的使用者。