【源码阅读】高效发布npm包利器——release-it

806 阅读5分钟

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

  1. 版本冲突监测;
  2. git 提交、打 tag、推送分支等功能;
  3. 利用 hook 来执行任意你想执行的命令;
  4. 在 GitHub 或 Gitlab 上创建发布分支;
  5. 生成变更日志;
  6. 管理 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,然后按照提示执行即可。

image.png

最后在npmjs上查看自己发布的包的状态,搞定。

2.3.2 自动更新 CHANGELOG

上面命令虽然可以在控制台看到变更日志,但是没有写入到 CHANGELOG.md 文档中,想要实现 2.1 中第5条,还需要继续下面的配置。

这里本人使用传统的日志方式来更新变更日志,其他方式可参考release-it changelog

  1. 安装生成日志插件:npm install @release-it/conventional-changelog --save-dev
  2. 根目录下创建 CHANGELOG.md 文件;
  3. release-it.json 中写入配置:
    {
      "plugins": {
        "@release-it/conventional-changelog": {
          "preset": "conventionalcommits",
          "header": "# Changelog",
          "infile": "CHANGELOG.md"
        }
      }
    }
    

最后,查看生成的变更文档。

image.png

有些简陋,不过可以自己定义模板,参见

查看,变更链接,既有日志记录,也有代码变更情况,完美。

image.png

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. 总结与收获

  1. 通过本次“源码阅读”,来要求自己不断的思考、实践和总结,改掉自己以前拖拉的毛病(说好一两个月要输出技术分享文档,然后就没有然后了);
  2. 收获高效工具一枚——release-it,提高工作效率(又可以有时间偷一会懒,哈哈);