- 本文参加了由公众号@若川视野 发起的每周源码共读活动, 点击了解详情一起参与。
- 第39期 | 如何发布一个 npm 库,自动化管理版本号、生成 changelog、tag 等
1. 前言
想必大家在使用第三方npm库时,很好奇作者们是如何进行包版本管理和发布,且保证不会出现版本号断裂(版本不连续,如有 0.1.2 和 0.1.4,但0.1.3缺失,本人就看到过这种情况)。
在没有接触 release-it 之前,说实在话,本人也是靠肉眼来保证版本连续,包括 alpha、bata 等类型的版本的发布。每次都很小心,别人发布时自己还要 check 一下(不放心)。是时候改变自己的工作方式,解放双眼,早点下班。
2. release-it 介绍与使用
2.1 功能介绍
当前工具提供了以下功能,具体可看release-it README.md:
- 版本冲突监测;
- git 提交、打 tag、推送分支等功能;
- 利用 hook 来执行任意你想执行的命令;
- 在 GitHub 或 Gitlab 上创建发布分支;
- 生成变更日志;
- 管理 pre-release 版本;
2.2 安装
安装之前,先检查自己的 nodejs 版本,nodejs 14版本以上,安装最新版本就可 npm i release-it;nodejs 10或12等老版本的安装使用该命令 npm i release-it@^14 进行安装。
首次安装,将提示使用何种方式保存配置文件,这里本人选独立文件 release-it.json 。
安装完毕后,可以看到 package.json 中多了一条命令:
{
"scripts": {
"release": "release-it"
}
}
2.3 命令与使用场景
2.3.1 版本发布
使用该工具,核心功能是发布包到npm上,因此,在进行下面操作之前,请确保自己本地已经登录到 npm,命令为 npm login。
【特别提醒】:确保本地源服务是 registry.npmjs.org/ ,由于大家知道的原因,国内大家都喜欢使用taobao镜像源,但是发布不能发到该服务器上。本人使用 nrm 工具进行镜像源的管理和切换。
登录成功后,执行命令 npm run release,然后按照提示执行即可。
最后在npmjs上查看自己发布的包的状态,搞定。
2.3.2 自动更新 CHANGELOG
上面命令虽然可以在控制台看到变更日志,但是没有写入到 CHANGELOG.md 文档中,想要实现 2.1 中第5条,还需要继续下面的配置。
这里本人使用传统的日志方式来更新变更日志,其他方式可参考release-it changelog:
- 安装生成日志插件:
npm install @release-it/conventional-changelog --save-dev; - 根目录下创建 CHANGELOG.md 文件;
- 在
release-it.json中写入配置:{ "plugins": { "@release-it/conventional-changelog": { "preset": "conventionalcommits", "header": "# Changelog", "infile": "CHANGELOG.md" } } }
最后,查看生成的变更文档。
有些简陋,不过可以自己定义模板,参见。
查看,变更链接,既有日志记录,也有代码变更情况,完美。
2.3.3 不发布只测试可使用参数 --dry-run
该命令不会将包发到npm上,其他命令会执行,包括提交代码、生成日志等。
但该方法不建议使用,容易导致正常发版时,跳过该版本,导致版本出现断裂(本人实测时就出现了0.2.2没发上去,尴尬)。
3. 技术原理探究
说了这么多,让我们看看它是如何实现,源码搞起。
通读源码后,发现核心代码如下:
const name = await reduceUntil(plugins, plugin => plugin.getName());
const latestVersion = (await reduceUntil(plugins, plugin => plugin.getLatestVersion())) || '0.0.0';
const changelog = await reduceUntil(plugins, plugin => plugin.getChangelog(latestVersion));
根据当前设置的插件,获取到上一次发布的版本号和变更记录,以此为依据,计算出本次发布的建议版本(命令问答时的提示,可以自己填写其他可用的版本号)。
本工具内置了 git 操作的插件,可以看到其发布过程的核心,还是 git 的 commit、tag、push 等命令的组合:
async release() {
const { commit, tag, push } = this.options;
await this.step({ enabled: commit, task: () => this.commit(), label: 'Git commit', prompt: 'commit' });
await this.step({ enabled: tag, task: () => this.tag(), label: 'Git tag', prompt: 'tag' });
return !!(await this.step({ enabled: push, task: () => this.push(), label: 'Git push', prompt: 'push' }));
}
4. 一些问题
4.1 登录npm,网络连接超时,提示 connect ETIMEDOUT;
本人,刚开始开了代理,导致登录不了。这里有点奇怪的是,打开代理是为了快速访问www.npmjs.com/ ,但是命令行登录却不行,猜测可能网络节点不一样,关闭代理后可行。
4.2 使用 nrm 切换npm源,总是“无法加载文件 *\node\node_global\nrm.ps1”
本人最初在 powerShell 上操作,发现该问题。找到目标目录,发现该文件存在,应该不是文件问题。由于本人运行环境为 window 11,猜测跟系统或者 powerShell 有关。根据提示找到 官网说明 ,果然和 powerShell 的权限配置有关。由于和本次分享无关,就不多说,直接给出解决方案。执行下面命令,调整当前用户权限设置,允许本机运行 .ps1 脚本。
Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope CurrentUser
另外一种方法,不用powerShell,改用其他cmd工具(有点偷懒的味道)。
4.3 登录npm,输入邮箱,提示“Please check your email for a one-time password”
这是npm的二次验证规则(以前好像没有,至少3个月前没有)。查看自己填写的邮箱,是否收到npm的邮件,里面有 OTP 口令,填写完成即可通过验证。猜测是很多人以前胡乱填写邮箱(图省事,我也这样干过),现在要整顿起来。
5. 总结与收获
- 通过本次“源码阅读”,来要求自己不断的思考、实践和总结,改掉自己以前拖拉的毛病(说好一两个月要输出技术分享文档,然后就没有然后了);
- 收获高效工具一枚——release-it,提高工作效率(又可以有时间偷一会懒,哈哈);