除了打包应用程序,webpack 还可以打包 JavaScript 库。以下指南适用于希望简化打包策略的库作者。
参考链接:https://www.webpackjs.com/guides/author-libraries/
output.library
参考链接:https://juejin.cn/post/7004340117112356900
在 Webpack 中,output.library
用于将你的打包结果导出为一个库,使其可以在其他环境中使用,比如在浏览器中通过 <script>
标签引入,或者在 Node.js 中通过 require
引入。
用法和例子
假设你有一个 JavaScript 模块需要打包成一个库,以便在其他项目中使用。你可以通过 output.library
来配置导出的库名称。
例子
假设你有一个简单的数学库:
// src/math.js
export function add(a, b) {
return a + b;
}
export function subtract(a, b) {
return a - b;
}
你希望将这个模块打包成一个库,库的名字叫 MyMathLib
。可以这样配置 Webpack:
// webpack.config.js
module.exports = {
entry: './src/math.js',
output: {
filename: 'math.bundle.js',
path: __dirname + '/dist',
library: 'MyMathLib', // 库的名称
},
};
解释
library: 'MyMathLib'
: 指定导出的库名称。在浏览器中,这个库会作为全局变量MyMathLib
使用。
使用
打包后,你可以在浏览器中通过 <script>
标签引入,并通过全局变量访问:
<script src="dist/math.bundle.js"></script>
<script>
console.log(MyMathLib.add(2, 3)); // 输出: 5
</script>
或者在 Node.js 中使用:
const MyMathLib = require('./dist/math.bundle.js');
console.log(MyMathLib.add(2, 3)); // 输出: 5
通过 output.library
,你可以将模块打包成一个可复用的库,方便在不同环境中使用。
作为一个库作者,我们希望它能够兼容不同的环境。换言之,用户应该能够通过多种方式使用打包后的库,比如CommonJS、AMD,配置方式是增加type属性。
// webpack.config.js
module.exports = {
entry: './src/math.js',
output: {
filename: 'math.bundle.js',
path: __dirname + '/dist',
library: {
name: 'MyMathLib', // 库的名称
type: 'umd'
}
},
};
外部化lodash
webpack
的 externals
配置用于指定哪些模块不应该被打包进输出的 bundle,而是在运行时从外部环境获取。这在以下情况下非常有用:
- 避免重复打包:如果某些库已经通过
<script>
标签在 HTML 中引入,可以通过externals
来避免重复打包。 - 减小 bundle 体积:通过不打包某些大型库,可以显著减小输出文件的大小。
- 兼容性:在不同模块系统中使用外部库。
如何使用 externals
可以通过在 webpack.config.js
中配置 externals
来实现:
module.exports = {
// 其他配置...
externals: {
// 示例1:直接指定模块名
jquery: 'jQuery',
// 示例2:对象形式,适用于多种模块系统
lodash: {
commonjs: 'lodash',
commonjs2: 'lodash',
amd: 'lodash',
root: '_',
},
},
};
配置说明
-
字符串形式:直接指定一个全局变量名。例如,
jquery: 'jQuery'
表示在打包时,require('jquery')
将从全局变量jQuery
获取。 -
对象形式:可以为不同的模块系统指定不同的外部访问方式。
commonjs
和commonjs2
:用于 CommonJS 模块系统。amd
: 用于 AMD 模块系统。root
: 用于浏览器环境中的全局变量。
现在,如果执行 webpack,你会发现创建了一个体积相当大的文件。查看文件可以发现 lodash 也被打包到代码中。在这种场景中,我们更倾向于把 lodash 当作 peerDependency,即使用者应该已经自行安装过 lodash,这样便可以放弃控制此外部库,将控制权让给使用此库的开发者。
使用 externals 配置即可实现上述目标:
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: '_',
},
},
};
lib / es / dist 是通过三个不同的模块系统打包生成的
- es:es module模块系统
- lib: commonjs模块系统
- dist:UMD模块系统
其实,打成哪种模块的包是根据.babelrc.js配置来的,如下:
然而,在babel v7.13.0版本后,useESModules被废弃掉了,如下: