❝允许奇迹发生 ❞
大家好,我是「柒八九」。一个「专注于前端开发技术/Rust
及AI
应用知识分享」的Coder
。
前言
还记得之前我们讲过如何在 npm 上发布二进制文件?吗。我们通过npm
将我们之前在Rust 赋能前端-开发一款属于你的前端脚手架中生成Rust
二进制文件发布到npm
仓库中。
如果想体验上述功能,可以通过npm
全局安装f_cli_f[1]在本地体验一下。
如果,你不想把自己的npm
发布到公网上,那么我们还可以将我们的npm
发布到公司内网上。这个我们在如何在gitlab上发布npm包介绍过了。
但是呢,在如何在gitlab上发布npm包
中我们只是介绍了如何发布一个正常的npm
,并且还不涉及各个包直接的关联。如果,我们想在gitlab
发布二进制类型的包,同时还涉及多个包直接的交互呢,上面的方案就有点捉襟见肘了。
那么,我们今天就聊聊,如何在「gitlab发布npm二进制包」并且我们还会涉及npm包
直接的互相操作。
好了,天不早了,干点正事哇。
我们能所学到的知识点
❝
- 项目结构
- 发布子包到gitlab 仓库
- 主包逻辑
- 全局安装并执行
❞
1. 项目结构
我们采用和之前发布到npm
的目录结构几乎一样。
有四个包
f_cli_windows_x64
:f_cli
适配Windows
架构f_cli_darwin_x64
:f_cli
适配MACOS_Intel64
架构f_cli_darwin_arm64
:f_cli
适配MACOS_ARM64
架构f_cli
:主包,用户根据用户操作环境下载对应的二进制文件
2. 发布子包到 gitlab 仓库
子包有3个,分别针对我们常见的开发环境。其实它们的内容极其简单。这个和之前在如何在 npm 上发布二进制文件?中是一样的。
"f_cli_darwin_arm64"/"f_cli_darwin_x64" ├── package.json └── bin/ └── f_cli
"f_cli_windows_x64"
├── package.json
└── bin/
└── f_cli.exe
在bin
文件中存放的就是我们脚手架编译后的二进制文件。
❝由于这三个子包的处理方式都出奇的一致。我们就随意挑选一个来讲解
❞
创建.npmrc
在如何在gitlab上发布npm包讲过,如果要在gitlab
发布npm
私包,我们需要创建一个.npmrc
。
@<your-scoop>:registry=https://公司gitlab域名/api/v4/npm/
//公司gitlab域名/api/v4/projects/<your_project_id>/packages/npm/:_authToken=${AUTH_TOKEN} </code></pre></div></div><blockquote><p>❝当然,我们还需要在<code>gitlab</code>中构建一个空项目,这步就省略了。 ❞</p></blockquote><p>上面有几个参数我们需要变更</p><ol class="ol-level-0"><li><code><your-scoop></code>:这里设置我们的想要的名称,这里我们设置为<code>cli</code></li><li><code><your_project_id></code>:这是我们<code>demo</code>项目在<code>gitlab</code>的id,这个我们可以在<code>Settings->General->Project ID</code>获取<figure class=""><div class="rno-markdown-img-url" style="text-align:center"><div class="rno-markdown-img-url-inner" style="width:auto"><div style="width:100%"><img src="https://cdn.static.attains.cn/app/developer-bbs/upload/1722821594349211896.png" /></div></div></div></figure></li><li><code>AUTH_TOKEN</code>我们使用环境变量来处理,这个变量在主页面的<code>Settings->Repository->Deploy tokens</code>中设置<code>token</code>。<ul class="ul-level-1"><li></li></ul><figure class=""><div class="rno-markdown-img-url" style="text-align:center"><div class="rno-markdown-img-url-inner" style="width:auto"><div style="width:100%"><img src="https://cdn.static.attains.cn/app/developer-bbs/upload/1722821594682747648.png" /></div></div></div></figure></li></ol><blockquote><p>❝别忘记,在生成token时,将值保存起来。 ❞</p></blockquote><h3 id="cjafm" name="%E4%BF%AE%E6%94%B9package.json"><strong>修改package.json</strong></h3><p>我们在<code>package.json</code>中还需要新增<code>publishConfig</code>,这是用于<code>npm publish</code>时用的。</p><div class="rno-markdown-code"><div class="rno-markdown-code-toolbar"><div class="rno-markdown-code-toolbar-info"><div class="rno-markdown-code-toolbar-item is-type"><span class="is-m-hidden">代码语言:</span>javascript</div></div><div class="rno-markdown-code-toolbar-opt"><div class="rno-markdown-code-toolbar-copy"><i class="icon-copy"></i><span class="is-m-hidden">复制</span></div></div></div><div class="developer-code-block"><pre class="prism-token token line-numbers language-javascript"><code class="language-javascript" style="margin-left:0">{ //... "publishConfig": { "@cli:registry": "https://公司gitlab域名/api/v4/projects/project_ID/packages/npm/" } } </code></pre></div></div><h3 id="937eq" name="%E5%8F%91%E5%B8%83%E5%8C%85"><strong>发布包</strong></h3><p>最后,我们使用</p><div class="rno-markdown-code"><div class="rno-markdown-code-toolbar"><div class="rno-markdown-code-toolbar-info"><div class="rno-markdown-code-toolbar-item is-type"><span class="is-m-hidden">代码语言:</span>javascript</div></div><div class="rno-markdown-code-toolbar-opt"><div class="rno-markdown-code-toolbar-copy"><i class="icon-copy"></i><span class="is-m-hidden">复制</span></div></div></div><div class="developer-code-block"><pre class="prism-token token line-numbers language-javascript"><code class="language-javascript" style="margin-left:0">AUTH_TOKEN=XXX npm publish </code></pre></div></div><p>将本地的二进制包发布到了<code>gitlab</code>。可以看出,我们使用的手动发布的方式。是因为,我们这三个子包其实内部没啥逻辑,只是一个二进制文件,所以我们就选择了用<strong>「手动发布」</strong>的方式。</p><p>随后,我们就可以在<code>demo</code>项目中的<code>Deploy->Package Registry</code>中看到发布成功的包</p><figure class=""><div class="rno-markdown-img-url" style="text-align:center"><div class="rno-markdown-img-url-inner" style="width:auto"><div style="width:100%"><img src="https://cdn.static.attains.cn/app/developer-bbs/upload/1722821594998874370.png" /></div></div></div></figure><figure class=""><hr/></figure><h2 id="cgvg7" name="3.-%E4%B8%BB%E5%8C%85%E9%80%BB%E8%BE%91"><strong>3. 主包逻辑</strong></h2><p>下面到了我们这篇文章的核心部分。</p><p>其实,主包的目录结构也很简单。</p><figure class=""><div class="rno-markdown-img-url" style="text-align:center"><div class="rno-markdown-img-url-inner" style="width:auto"><div style="width:100%"><img src="https://cdn.static.attains.cn/app/developer-bbs/upload/1722821595356263037.png" /></div></div></div></figure><h3 id="c5imn" name="%E6%96%B0%E5%A2%9E.npmrc"><strong>新增.npmrc</strong></h3><p>还是一样的套路。</p><div class="rno-markdown-code"><div class="rno-markdown-code-toolbar"><div class="rno-markdown-code-toolbar-info"><div class="rno-markdown-code-toolbar-item is-type"><span class="is-m-hidden">代码语言:</span>javascript</div></div><div class="rno-markdown-code-toolbar-opt"><div class="rno-markdown-code-toolbar-copy"><i class="icon-copy"></i><span class="is-m-hidden">复制</span></div></div></div><div class="developer-code-block"><pre class="prism-token token line-numbers language-javascript"><code class="language-javascript" style="margin-left:0">@<your-scoop>:registry=https://公司gitlab域名/api/v4/npm/ //公司gitlab域名/api/v4/projects/<your_project_id>/packages/npm/:_authToken=${AUTH_TOKEN}
只不过需要将上面的信息,置换成主包的相关内容。
修改package.json
由于是主包,我们就需要额外的操作,这里就两点需要新增
bin
publishConfig
{
"bin": {
"front_cli": "bin/cli"
},
"publishConfig": {
"@cli:registry": "https://gitlab.com/api/v4/projects/project_ID/packages/npm/"
},
}
publishConfig
就不用多说了,就是给npm
发布用的。而bin
中指定的信息就是,当此软件包「全局安装」时,该文件将链接到全局 bins
目录内,或者将创建一个 cmd
(Windows
命令文件)来执行 bin
字段中的指定文件,因此可用于由 name
或 name.cmd
(在 Windows PowerShell
上)运行。更过的可以参考package.json_bin[2]
当然,如果我们使用像nvm/fnm
等node
版本管理工具的话,也会在指定的地方进行配置。最终的结果就是,可以使得我们的包能够在全局访问并且执行对应的命令。
由于,我们本机使用的是fnm
,然后在主包被全局安装后,在对应的node
文件夹中就会新增对应的信息。
bin/cli
这个和之前我们讲如何在 npm 上发布二进制文件?不同。
我们之前在package.json
中还有
{
"scripts": {
"postinstall": "node ./install.js"
},
}
也就是在包被安装后,会自动触发postinstall
命令,执行node ./install.js
。里面就是根据各种平台信息和对应包的下载。
下面是之前install.js
的主要逻辑。
但是呢,我们从本地安装发布到gitlab
的私包时,它不触发postinstall
的命令,也就是在主包下载后,无法下载对应的子包。那意味着我们的这个功能直接垮掉。
所以,我们索性取消掉postinstall
的逻辑,将下载和执行二进制的路径都迁入到bin/cli
中。
对比之前的install.js
的逻辑,粗看下,其实没啥变化。主要流程还是根据process.platform
和process.arch
确定平台和架构,然后从BINARY_DISTRIBUTION_PACKAGES
查找对应的信息。
BINARY_DISTRIBUTION_PACKAGES
由于我们发布的位置和名称也发生变化。这里的BINARY_DISTRIBUTION_PACKAGES
也有些许变更。
const BINARY_DISTRIBUTION_PACKAGES = {
'darwin-x64': '@cli/x64',
'darwin-arm64': '@cli/arm64',
'win32-x64': '@cli/windows_x64',
}
其实还有几点也发生了变化。之前我们是从npm
中下载二进制包。由于我们在npm
发布的公共包,也就意味着所有人都可以通过ajax
进行获取。但是呢,我们现在也想通过ajax
在node
项目中获取gitlab
私包。这就需要提供额外的信息。
- projectID
- 授权信息
projectID
被存放在了PROJECT_ID_MAP
中。
const PROJECT_ID_MAP = {
'darwin-x64': '1',
'darwin-arm64': '2',
'win32-x64': '3',
}
然后,授权就是我们在进行异步接口时候,需要通过header
的Authorization
字段提供。而这个字段的值就是之前我们申请的Deploy token
(是不是让你保存了)。
我们之前提过,由于postinstall
命令不好使,我们就把之前的install.js
和bin/cli
的逻辑合二为一了。
那就意味着现在bin/cli
在被执行时,下载对应平台的二进制文件,并且根据参数执行命令。
downloadBinaryFromGitlab
这里我们分了两种情况
- 首次全局安装,那就需要下载对应的二进制文件并执行
- 非首次安装,那就直接执行对应的二进制文件就行。
剩余的逻辑和之前是一样的。
makeRequest
这里也是一个重点。
这里和之前的方法也有几点不同。
- 新增了
token
参数 - https新增了
options
- 根据数据返回的多少,显示了下载进度信息
先看makeRequest
如何被调用。
const tarballDownloadBuffer = await makeRequest(
https://公司gitlab域名/api/v4/projects/${projectID}/packages/npm/${platformSpecificPackageName}/-/${platformSpecificPackageName}-${BINARY_DISTRIBUTION_VERSION}.tgz
,
"glpat-xxx"
)
我们来简单解释一下,由于我们现在是从gitlab
拉取私库,都说了是私库,那势必就有鉴权处理。这里的token
就是接收之前的Deploy Token
。
然后,将接收到的token
放到https
的options
的headers
中。
针对这点,我们可以从gitlab官网[3]查看。
针对进度信息的展示,也是很简单的逻辑,就是基于response
的data
事件,每次跟新downloaded
,并且用process.stdout.write
输出到控制台。
发布主包
虽然,主包看起来逻辑比较多,但是在发布时,也是一句话搞定
AUTH_TOKEN=XXX npm publish
随后,我们就可以在gitlab
中看到发布的包信息了。
4. 全局安装并执行
既然,我们已经将主包发布到了gitlab
,那我们就需要使用其他方式将其下载到本地,然后执行对应的命令。
修改全局.npmrc
之前的文章讲过,如果想要下载gitlab
的私包,那就需要修改本地.npmrc
和全局.npmrc
。
因为,我们要全局安装,所以我们直接修改全局.npmrc
。
使用open ./.npmrc
打开.npmrc
并加入如下命令
@cli:registry=https://公司gitlab域名/api/v4/projects/projectId/packages/npm
//公司gitlab域名/api/v4/projects/projectId/packages/npm/:_authToken=glpat-xxxx
大家根据自己的实际情况修改上述内容。
全局安装
在全局安装之前,我们可以使用npm list -g
来看看自己在特定node
环境下,全局安装了啥。
然后,我们使用npm i @cli/cli -g
来全局安装。由于我本地已经安装过了,这里就不贴图了。
我们可以使用npm list -g
来查看是否安装成功,亦或者直接在控制台中输入front_cli
命令。
反正,只有不是提示没对应的文件那就是安装成功了。然后,我们就可以开开心心的使用这个命令了。
完美完结🎉🎉🎉🎉