除了打包应用程序,webpack 还可以用于打包 JavaScript library
我们跟随官方指南的例子(对一些必要依赖做了升级处理) 编写一个名为 webpack-numbers 的小的 library,可以将数字 1 到 5 转换为文本表示,反之亦然,例如将 2 转换为 'two'。 项目结构为
├── .babelrc
├── .eslintrc.json
├── index.js
├── package.json
├── ref.json
├── webpack.config.js
└── yarn.lock
.babelrc
{
"presets": [
"@babel/env",
"@babel/preset-react"
]
}
.eslintrc.json
{
"env": {
"browser": true,
"commonjs": true,
"es6": true,
"node": true
},
"extends": "eslint:recommended",
"parserOptions": {
"sourceType": "module"
},
"rules": {
"indent": [
"error",
4
],
"linebreak-style": [
"error",
"unix"
],
"quotes": [
"error",
"single"
],
"semi": [
"error",
"always"
]
}
}
上面两个是esLint相关的配置文件
index.js
import _ from 'lodash';
import numRef from './ref.json';
function createTransalator() {
return {
numtoword: (num) => {
return num < 0 || num > 5 ? 'This is a failure' : converttoword(num);
},
wordtonum: (word) => {
const num = converttonum(word);
return num === -1 ? 'This is a failure' : num;
}
};
}
const converttoword = (num) => {
return _.reduce(numRef, (accum, ref) => {
return ref.num === num ? ref.word : accum;
}, '');
};
const converttonum = (word) => {
return _.reduce(numRef, (accum, ref) => {
return ref.word === word && word.toLowerCase() ? ref.num : accum;
}, -1);
};
export default createTransalator();
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"
}]
package.json
{
"name": "y",
"version": "1.0.0",
"description": "An example of how to author libraries using webpack",
"main": "dist/webpack-numbers.js",
"scripts": {
"build": "webpack",
},
"keywords": [
"webpack",
"webpack-library",
"bundling",
"library"
],
"author": "pksjce",
"license": "ISC",
"devDependencies": {
"@babel/core": "^7.13.1",
"@babel/preset-env": "^7.13.5",
"@babel/preset-react": "^7.12.13",
"babel-loader": "^8.2.2",
"babel-plugin-add-module-exports": "^0.2.1",
"eslint": "^7.21.0",
"eslint-loader": "^4.0.2",
"lodash": "^4.17.21",
"webpack": "^5.4.0",
"webpack-cli": "^4.2.0"
}
}
接下来我们写基本的webpack文件
webpack.cofig.js
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'webpack-numbers.js',
},
};
-
我们的模块需要lodash依赖,但是我们期望library的使用者已经安装了lodash依赖,否则我们需要将lodash打包入文件,在这种场景中,我们更倾向于把 lodash 当作 peerDependency。也就是说,consumer(使用者) 应该已经安装过 lodash
-
我们期望我们的library可以通过多种方式被引入使用:
- CommonJS
const webpackNumbers = require('webpack-numbers');
- AMD
require(['webpackNumbers'], function (webpackNumbers) {
// ...
webpackNumbers.wordToNum('Two');
});
- Node.js
<!DOCTYPE html>
<html>
...
<script src="https://unpkg.com/webpack-numbers"></script>
<script>
// ...
// 全局变量
webpackNumbers.wordToNum('Five');
// window 对象中的属性
window.webpackNumbers.wordToNum('Five');
// ...
</script>
</html>
- 或者作为一个全局变量
修改配置
const path = require('path');
module.exports = {
entry: './index.js',
output: {
path: path.resolve(__dirname, './dist'),
filename: 'webpack-numbers.js',
libraryTarget: 'umd',
globalObject: 'this',
// libraryExport: 'default',
library: 'webpackNumbers'
},
externals: {
'lodash': {
commonjs: 'lodash',
commonjs2: 'lodash',
amd: 'lodash',
root: '_'
}
},
module: {
rules: [
{
test: /\.(js)$/,
exclude: /(node_modules|bower_components)/,
use: 'babel-loader'
}
]
},
};
关于library,这个字段配合libraryTarget一起使用,libraryTarget默认值为'var',意味着,该依赖引入后返回的值为你设置的library(这里为webpack-numbers.js)’,我们这里设置libraryTarget: 'umd';因为我们期望我们的库可以通过多种方式引入 参考文档:libraryTarget
globalObject:意味着我们当全局引入该依赖时我们从哪个变量来读取,这里我们写的this,以为这我们可以从this下面读取webpackNumbers
externals:我们不将lodash打包进入我们的library,这意味着你的 library 需要一个名为 lodash 的依赖,这个依赖在 consumer 环境中必须存在且可用。
最后,执行 yarn build