除了打包应用程序,webpack 还可以用于打包 JavaScript library。
https://webpack.docschina.org/guides/author-libraries/
https://webpack.docschina.org/configuration/output#output-librarytarget
1)创建
案例:
mkdir library
cd library
npm init -y //多出个package.json(--yes)
mkdir src
cd src/
touch math.js string.js index.js
math.js:
export function add(a, b) {
return a + b;
}
export function minus(a, b) {
return a - b;
}
export function multiply(a, b) {
return a * b;
}
export function devision(a, b) {
return a / b;
}
string.js:
export function join(a, b) {
return a + '' + b;
}
index.js:
index.js:
import * as math from "./math";
import * as string from "./string";
export default { math, string };
webpack.config.js:
const path = require("path");
module.exports = {
mode: "production",
entry: "./src/index.js",
output: {
filename: "library.js",
path: path.resolve(__dirname, "dist"),
}
};
npx webpack后生成dist/library.js 则这个library.js就是我们导出的库
2)使用
一般一个模块引用的方式有很多种:ES module(import from)、commonjs、AMD、CMD、script标签引入等,不同的引入方式还需在打包库模块时添加不同的配置。
import library from 'library'; //ES module
const library = require('library'); //commonjs
require(["library"], function(library){ //AMD
//library.x
})
以上三种方式使用需要在webpack.config.js中配置libraryTarget,来确定library的暴露形式
有以下几种方式暴露 library:
如果设置了 library 但没有设置 libraryTarget,则 libraryTarget 默认指定为 var,详细说明请查看 output 文档。查看 output.libraryTarget 文档,以获取所有可用选项的详细列表。
在html页面中通过script、全局引用,并通过全局变量如library去使用这个库中的内容library.X,需要配置library: "library"
//library.X
webpack.config.js:
output: {
filename: "library.js",
path: path.resolve(__dirname, "dist"),
library: 'library', //暴露library:增加全局变量library,通过script标签引入js,并通过library全局变量使用
libraryTarget: 'umd' //控制以不同形式暴露library,umd:AMD、commonjs、ES import等任何方式都可以引入,this:将上面的全局变量挂载到this上,window同理,node下是global
}
思考:
若以上的string.js使用了lodash这个库,如下:
import _ from 'lodash';
export function join(a, b) {
return _.join([a, b], ' ');
}
当其他人使用上面导出的library库的同时,整个业务逻辑代码中还需要用到lodash
import _ from 'lodash';
const library = require('library');
问题:library中使用了lodash,第三方业务也需要使用lodash=》导致lodash重复引用
解决:打包library时配置externals,排除lodash被打包到library中,而是使用library时额外引入lodash,这样无论业务逻辑中是否需要lodash,都必须引入,而且上面的引入也不会有问题
module.exports = {
//externals: "lodash", //字符串"lodash"、数组["lodash"]、对象{lodash: "lodash"},打包的时候遇到lodash忽略,不把lodash打包到输出文件中 这样输出的库在使用时需要引入lodash
externals: {
lodash: { //commonjs环境下引入lodash必须叫lodash不能叫_等其他名
root: "_", //通过script标签引用而不是ES import、commonjs、AMD方式,必须像全局注入_变量,
commonjs: "lodash" //lodash库在commonjs环境中使用
}
}
}
commonjs:
const lodash = require('lodash');
const library = require('library');
externals:https://webpack.docschina.org/configuration/externals/
从输出的 bundle 中排除依赖,防止将某些 import 的包(package)打包到 bundle 中,而是在运行时(runtime)再去从外部获取这些扩展依赖(external dependencies)。此功能通常对 library 开发人员来说是最有用的。
externals:string object function regex(正则)
外部 library 可能是以下任何一种形式:
注意:上面只是打包库最简单的配置,正常打包一个复杂的node模块,需要考虑按需加载、按顺序加载、tree shaking等等。
3)发布
打包库成功后,修改package.json中的入口:
{
...
"main": "./dist/library.js",
...
}
或者:module 属性应指向一个使用 ES2015 模块语法的脚本
{
...
"module": "src/index.js",
...
}
在npm网站上注册账号并登陆
在bash中输入npm adduser回车,输入用户名密码,
npm publish发布到npm的仓库上
发布成功之后别人就可以使用这个库:npm install安装库即可(安装包名看package.json中的name,注意库名不能重复,否则npm publish会报错)