前端体系化建设 - NPM包自动发布

4,005 阅读3分钟

我们设想一个开发场景

  1. 我们使用ts进行开发工具包
  2. 当我们开发完毕后,我们进行代码合并,并打出版本tag进行版本归档
  3. 触发CI,进行远程构建动作
  4. 将构建结果发布到我们的NPM包管理当中

本文介绍在 gitlab 下面使用 CI/CD 发布前端包到 npm 的方法,让npm的包和代码仓库关联起来,同时省去手动的npm publish动作

image.png

如果你不是适用的 gitlab,不用担心,脚本部分仍然对你有很大帮助

对于没有使用 gitlab 的小伙伴,可以使用这篇文章做一下基础的 gitlab 搭建 在 gitlab 中玩转 CI/CD(juejin.cn)

前期准备

1. 新建代码仓库

可以参考这个仓库的代码,请把 gitlab-ci.yml 文件删除哦 ~ 点我下载

1. 生成 npm token 备用

  1. 登陆 npm 官网,进行token获取

image.png

新建一个token

image.png

建好的token保存下来备用,找到profile, 打开2FA

image.png

4. 将 token 设置成环境变量

image.png

首次注册需要验证邮箱npm发布报错 :403 Forbidden - PUT https://registry.npmjs.org - SegmentFault 思否

配置 CI/CD

1. 配置ci文件

一个 gitlab-ci.yml 文件如下所示, build 表示的是构建阶段的名称,是一个 stagescript 则表示这个阶段的脚本工作,这里做了简单的 npm i, 以及 tsc 构建工作,构建的输出目录和配置主要存在项目的 tsconfig.json 里面

image: node:latest

build:
  script:
  - npm install
  - ./node_modules/typescript/bin/tsc -p ./tsconfig.json

保存后,你会在 CI/CD 里面看到进行中的任务

image.png

image.png

2. 指定仅分支才触发构建

上面的 CI 逻辑,会被应用于所有的分支,一旦发生提交动作,就会启动,这明显是和我们的需求不符合的,我们希望仅在打 tag 的时候才发生构建动作,因此我们需要给我们的 build stage 增加 only 限定,让他只能对部分分支起作用

    only:
    - develop
    - release
    - master
    - /^dev_[0-9]+(?:.[0-9]+)+$/ # regular expression

only 语法如上,我们可以直接写死分支或者tag的名称,也可以使用正则表达式来做匹配命中,此处我们直接写版本号通配符

    only:
      - /^\d+\.\d+\.\d+$/

当我们打的tag满足 1.0.0 类似的这种格式时,就会触发构建,当然也可以加上一下小尾巴,比如

    only:
      - /^\d+\.\d+\.\d+$/ # 这是版本
      - /^\d+\.\d+\.\d+-beta-.*/ # beta版本

3. 使用 tag 号替换 package.json 的版本号

npm 上面的版本号,是根据 package.json 里面的 version 进行匹配的,因此我们在正式 publish 前,还需要修改 version 的版本号, 有的小伙伴可能会在打tag前,手动修改 package.json 文件,也无不可,这里我们直接在 CI 里面用脚本代码直接修改了, 相关的脚本如下

- file=`cat ./package.json` # 读取文件,并赋值到file变量里面
- echo ${file/\"version\":\ \"1.0.0\"/\"version\":\ \"`git describe`\"} > ./package.json

git describe 使用于获取当前的仓库描述信息,在打tag后执行的ci里面,得到的就是分支的名称,当然也可以使用 gilab 变量进行处理

echo xx > filePath 是将 xx 内容输出到指定文件之中,直接覆盖掉

${string/aa/bb} 是替换的语法,将string里面的 aa 换成 bb,此处将 "version": "1.0.0" 替换成 "version": "tag"

部分斜杠主要用于转义,可以在本地进行测试

echo ${string/\"version\":\ \"1.0.0\"/\"version\":\ \"`git describe`\"} > ./package.json

image.png

4. 进行无用的目录清理

上传前,我们尅将我们的源码以及一些过程文件等内容清理掉

- rm -rf src # 笔者使用的工程源代码在src
- rm -rf node_modules # 依赖不需要一起上传

5. 进行 npm publish

最后,配置 token,保证 npm publish 权限

- echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > .npmrc

执行发布,整个文件看起来就会像

# This file is a template, and might need editing before it works on your project.
# Official framework image. Look for the different tagged releases at:
# https://hub.docker.com/r/library/node/tags/
image: node:latest

build:
  script:
  - echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > .npmrc
  - npm install
  - ./node_modules/typescript/bin/tsc -p ./tsconfig.json
  - rm -rf src
  - rm -rf node_modules
  - string=`cat ./package.json`
  - echo ${string/\"version\":\ \"1.0.0\"/\"version\":\ \"`git describe`\"} > ./package.json
  - npm publish
  
  only:
    - /^v.*/ # 笔者版本打法都是 v开头

处理完后,就会看到发布的结果,注意,发布公有包的时候,需要将 package.json 里面的 private 这行删掉

image.png

image.png

进阶

  1. 受限于安全限制,公司的大部分包都不能直接挂到公网上面去,那么将包推到私有的包管理里面的确是有必要的,可以使用的是 A lightweight open source private npm proxy registry | Verdaccio 系统作为私有包管理,搭建完成后按上面的流程处理即可

  2. 理论上,我们不仅可以自动发布npm包,还可以在提交合并请求的时候,自动的从master打出一个tag,这个tag又会触发publish操作

其他

  1. 如果你的 runner 安装环境已经做好了npm login 的动作,那么可以不用配置token

参考

  1. shell字符串替换 - 简书 (jianshu.com)
  2. token的使用
  3. Continuously Deploying an NPM Package with GitLab CI/CD (webbureaucrat.gitlab.io)