本文介绍了如何把一个npm包同时发布到npm注册表和github的注册表,其它注册表同理。

需求背景

我有一个基于lerna的项目,包含了多个package,我一开始是发布到github pkg register的。虽然发github可以在仓库直接关联上,但是对于使用者来说会很麻烦,所以我就像能不能同时发到npm和github上。

解决方案

通过npm-multi-publish来支持这个功能,好处是不光npm publish可以自动发布到多个注册表,任何基于npm publish的都可以。例如lerna publish

实施步骤

  1. ~/.npmrc中增加对多个注册表的认证。 如下所示
//registry.npmjs.org/:_authToken=npm_xxxxxxxxxxxxxxxxxx
//npm.pkg.github.com/:_authToken=ghp_yyyyyyyyyyyyyyyyyy
  1. 验证是否登录成功,执行下列命令后会回显对应的用户名
npm whoami --registry=https://registry.npmjs.org/ 
npm whoami --registry=https://npm.pkg.github.com/
  1. 在package.json总增加对应的配置
{
    "publishConfig": [ // 注册表列表,有多少个写多少个
    {
      "registry": "https://registry.npmjs.org"
    },
    {
      "registry": "https://npm.pkg.github.com"
    }
  ],
  "scripts": { // 增加两个npm发布的生命周期钩子
    "prepublishOnly": "npm-multi-publish", //  在npm publish命令前执行
    "postpublish": "npm-multi-publish", // 在npm publish命令后执行
  }
}

  1. 执行npm publishlerna publish

原理

  1. 在执行npm publish后, 通过prepublishOnly拦截发布操作,提取publishConfig数组,然后使用第一个注册表项覆盖publishConfig配置,写入package.json文件,然后正常执行publish
  2. 通过postpublish钩子,但第一个注册表发布完成后,把publishConfig改成第二个注册表现,并写入文件。然后执行额外的npm publish
  3. 上一步的npm publish会继续触发postpublishprepublishOnly
  4. postpublish检测到所有的注册表都发布完之后,会复原package.json文件

注意事项

  1. 如果是发不到npm的组织中的话,需要先单独的npm publish --access public,因为默认会作为组织的私有包,如果没有花钱的话,手动指定为公开的包

  2. 如果已经在项目的.npmrc中指定该package的注册表,需要删除掉

相关链接