本文将会介绍如何将自己写的组件库打包成第三方库,发布到 npm 上,同时支持在原生 js / React/ Vue 下使用。Webpack4 的升级指南可以参考下 Webpack4.0 升级配置,本文不做赘述。

使用 Webpack4.0 打包

1
2
3
4
// src/index.js
exports default function Tree() {
console.log('Hello Tree')
}

假设我们有上面的 index.js 文件,我们想要把打它打包成一个 tree.js 和一个 tree.min.js 包,并且我希望我既可以通过 <script src="../dist/tree.js"></script> 直接 new Tree() ,又可以通过 import Tree from 'tree'let Tree = require('tree') 引入,怎么做呢?这就要使用 Webpack 来处理了。

Webpack 不仅可以打包 React / Vue 相关的项目工程,也可以单独打包 js 组件。先来看下入口与出口的配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
module.exports = {
//...
mode: "none",
entry: {
tree: "./src/index.js",
"tree.min": "./src/index.js"
},
output: {
filename: "[name].js",
libraryExport: "default",
library: "Tree",
libraryTarget: "umd"
}
//...
};

mode

Webpack4.0 会在默认情况下开启 mode=production,这会无差别的压缩我们的 tree.jstree.min.js,这不是我们想要的,禁用它。

entry

entry 里面我们配置两个入口 tree"tree.min",让 webpack 可以打包出两个文件,我们可以针对两个入口做不同的处理。

output

outputfilename 表示打包出来文件名叫什么。libraryExport=default 表示打包出来的组件直接对外暴露 default 属性,否则我们调用的时候需要 new Tree.default(),这不是我们希望的调用方式。library=Tree 表示对外暴露的组件叫什么,如果这个地方修改成了 library=Bar,那我们调用的时候就是 new Bar()libraryTarget=umd 表示采用 UMD (Universal Module Definition) 的方式打包 js,同时支持在 CommonJS、AMD 和全局变量使用。

optimization

怎么对 tree.min.js 压缩,但不对 tree.js 压缩呢?请看下面的配置部分:

1
2
3
4
5
6
7
8
9
10
// ...
optimization: {
minimize: true,
minimizer: [
new UglifyJSPlugin({
include: /\.min\.js$/,
}),
],
},
// ...

通过 include 设置只压缩 min.js 结尾的文件,是不是很简单。这样我们就得到了 dist/tree.min.jsdist/tree.js 两个文件。下面我们开始发布代码到 npm。

发布组件库到 npm 上

发布之前

发布之前,还有件事需要做,在项目根目录新建 index.js,添加内容

1
2
3
4
5
if (process.env.NODE_ENV === "production") {
module.exports = require("./dist/tree.min.js");
} else {
module.exports = require("./dist/tree.js");
}

修改 package.jsonmainindex.js,指定我们通过 import / require 的时候入口文件位置。

注册 npm

想要发布代码到 npm 上,需要先注册一个账号,你可以直接打开官网注册,这里我们选择更 cooooool 的方式注册。

1
npm adduser

依次输入 Username、Password、Email 完成注册。

登录 npm

注册好账号之后需要在 Terminal 上登录 npm,在 Terminal 中直接注册的同学就不需用登录了。

1
npm login

输入 Username、Password、Email 完成登录。

发布到 npm

1
npm publish

发布的包名就是你的 package.jsonnameversion。有冲突的话需要换一个哦。

最后

本文其实是笔者近期在开源的一个树形选择控件 @widgetjs/tree 摸索出来的打包经验总结。为了简化配置,突出重点,省略了一些生产环境需要添加的较为繁琐的细节,正式的生产模式配置可以在 github 上找到,也欢迎使用,多多提出意见。