科技微讯

发布私有 npm package 到 GitHub 的方法

如果你写的 npm 包只用于内部,不对外公开,可发布到 GitHub 的 npm registry。因为 npm 官方 registry 的免费账号不可以发布私有 package,不想花钱,GitHub 是最好的选择。

发布到 GitHub 的 npm package 如果没有和某个 repo 绑定,默认就是私有的,如果绑定了某个 repo,其可见性将和 repo 保持同步。

发布私有 package 到 GitHub,官方文档有较为详细的说明,但如果对 npm 的理解仅限于 npm installnpm uninstall,官方文档理解起来有难度。所以这篇文章先带大家了解 npm 的相关知识。

npm 相关知识

registry

当我们使用 npm 安装一个依赖时,npm 会从一个所谓的 registry website 查询并下载数据,默认的 registry 是 https://registry.npmjs.org,npm 允许你设置其他 registry,其中 GitHub 的 npm registry 是:https://npm.pkg.github.com

npm 把 registry 信息记录在 .npmrc 文件,使用 npm login 登录某个 registry 时会自动生成 .npmrc 并往里面写入相关信息,在 macOS 系统该文件位于 ~/.npmrc。比如我登录了 npm 官方 registry 和 GitHub 的 npm registry 后,~/.npmrc 将包含下面这段信息。每行冒号左边是省略了 https 的 registry 地址,冒号右边对应一个 token,用 _authToken 表示。

//registry.npmjs.org/:_authToken=npm_ohxxxxxxxxxxxxxx
//npm.pkg.github.com/:_authToken=ghp_D8xxxxxxxxxxxxxx

另一个生成 .npmrc 的方法是执行 npm config edit,该命令会在当前目录生成 .npmrc 文件,并开启编辑器让你修改里面的内容。如果想生成全局配置,需要使用 npm config edit --global。本地 .npmrc 优先级高于全局的 ~/.npmrc

.npmrc 只是 npm 获取配置信息的其中一种方式,我们也可以通过环境变量传入配置信息,或者直接在命令行传入配置信息。

npm gets its config settings from the command line, environment variables, and npmrc files. 出处

根据所在路径的不同,.npmrc 文件其实有四种,执行 npm config list 会展示当前目录下的 npm 配置信息,且会按照来源进行分类,例如 ; "cli" config from command line options 表示接下来的配置来自命令行工具的参数,; "user" config from ~/.npmrc 表示接下来的配置来自 ~/.npmrc 配置文件。

scope

scope 是 npm 另一个重要概念,在 npm 官方 registry 注册一个帐号,你的帐号名就是你的 scope,比如我的 npm 帐号用户名是 kejiweixun,所以我在 npm 官方 registry 的 scope 就是 @kejiweixun

在 npm 官方 registry 发布一个私有 package,必须把这个 package 发布到你的 scope 下,这意味着该 package 的名称必须带有 scope 前缀,例如 @kejiweixun/my-package。如果是发布公开 package,则没有这个要求。

事实上,凡是名称带有 scope 前缀且是发布到 npm 官方 registry 的 package,首次执行 npm publish 都会默认把它当作私有 package 发布出去,如果要公开发布,需执行:npm publish --access public

Private packages always have a scope, and scoped packages are private by default. 出处

正如开头所说,发布到 GitHub 的 package 默认就是私有,和名称是否有 scope 前缀无关。但 GitHub 规定仅支持 scoped package,所以也要在名称前加 scope 前缀,这里的 scope 就是你的 GitHub 用户名。

GitHub Packages only supports scoped npm packages. Scoped packages have names with the format of @owner/name.出处

关联 scope 和 registry

我们可以在 .npmrc 把一个 scope 和一个 registry 关联起来,关联方法主要有两种

  1. 执行 npm login 登录某个 registry 时,同时提供 scope 参数,例如关联 @kejiweixun 和 GitHub 需要执行:npm login --scope=@kejiweixun --registry=https://npm.pkg.github.com
  2. 手动编辑 ~/.npmrc 文件,请看下方例子最后一行,@kejiweixun 位于冒号左边,表示一个 scope,冒号右边是该 scope 所关联的 registry;
//registry.npmjs.org/:_authToken=npm_ohxxxxxxxxxxxxxx
//npm.pkg.github.com/:_authToken=ghp_D8xxxxxxxxxxxxxx

@kejiweixun:registry="https://npm.pkg.github.com/"

把 scope 和 registry 关联起来后,当我们 npm publish @my_scope/my-package,npm 会自动地把这个 package 发布到和 scope 关联的那个 registry,当我们 npm install @my_scope/my-package,npm 会自动地从和 scope 关联的那个 registry 查询并下载数据。

这就是关联 scope 和 registry 的目的和好处,非常方便。

如果一个 scope 未关联任何 registry,将使用默认 registry:https://registry.npmjs.org。如果默认 registry 没有你要找的模块,会报错,提示找不到。

--scope here is a unique identifier for a group of packages as introduced in NPM v2. A scope can be attached to a registry, and so every package published under that scope assumes that same registry. 出处

发布流程

有了以上基础知识,接下来分享如何发布一个私有 package 到 GitHub 的 npm registry。

  1. 打开 GitHub 创建一个 classic personal access token,权限选择 write:packages
  2. 使用 npm 登录 GitHub registry,按照提示输入用户名、密码,其中密码就是上一步拿到的 token;
npm login --scope=@kejiweixun --registry=https://npm.pkg.github.com --auth-type=legacy

--auth-type=legacy 是 npm 9 才需要添加的参数,--scope= 需要设置为 GitHub 用户名。这种登录方式把 @kejiweixun 这个 scope 绑定到了 GitHub 的 npm registry,登录成功后 ~/.npmrc 将包含如下配置信息,可执行 npm config list 查看:

//npm.pkg.github.com/:_authToken=ghp_D8xxxxxxxxxxxxxx

@kejiweixun:registry="https://npm.pkg.github.com/"

一个较好的做法是,在你的模块所在目录创建一个新的 .npmrc 文件,然后把上述最后一行从 ~/.npmrc 中剪出,粘贴到项目本地的 .npmrc。这样可避免两个 registry 的 scope 相同时造成的冲突。如果不想创建新的 .npmrc 文件,也可以在命令行添加 --registry 参数,例如发布一个模块时执行:

npm publish --"@kejiweixun:registry=https://npm.pkg.github.com/"
  1. 准备一个将要发布的 npm 模块;

  2. 打开这个 npm 包的 package.json 文件中,在 name 字段添加 scope 前缀,例如 @kejiweixun/my-package

  3. 管理版本号,可使用 standard-version,在 npm 增加一个类似下方的 script

"scripts": {
    "release": "standard-version && git push --follow-tags && npm publish"
}
  1. 发布:由于名称带有 scope 前缀,scope 又和 GitHub 的 registry 关联了,所以可以直接使用 npm publish 发布,如果 scope 和 GitHub registry 没有关联,那 npm 会自动把它发布到 npm 的官方 registry,如果你的 npm 用户名不同于 scope 名称,会发布失败;

  2. 安装:由于名称带有 scope 前缀,scope 又和 GitHub 的 registry 关联了,所以可以直接执行 npm install 安装,如果 scope 和 GitHub registry 没有关联,那 npm 会从其官方 registry 查找这个 package,可能会提示找不到;

GitHub 有一个独立的 Packages 栏目,这里展示了你发布的所有 package。默认情况下,这些 package 和它所对应的 repo 并不关联在一起。要想把 package 和 repo 关联在一起有两种方法:一是在后台手动关联;二是在 package.json 添加 "repository" 字段,其值设置为 repo 链接,这样发布后就自动关联了,关联后,这个 package 也会展示在 repo 中。

"repository":"https://github.com/OWNER/REPOSITORY",

总结

总结起来其实就三步:


参考文章:

暂无评论