从0到1搭建react组件库-发包篇

411 阅读7分钟

前言

完成组件库的一些基础组件库开发后,我们还需要将其发布、部署出去,供其他人查看和使用。 在这个流程中我们主要会面对两个场景:

场景一:

完成组件库的一些基础组件的开发工作后,我们可以在同一个 Monorepo 的仓库下进行引用。 但是如何实现像平日里的 Arco DesignAnt Design 等组件库直接通过 npm i *** 的命令下载到 node_modules 目录下进行使用呢?这里就需要引入 npm官网 了, 我们开发过后的包可以通过 publish 的指令发布到 npm 的注册表中,npm i *** 的命令就会索引下载对应的包。

场景二:

发布出去之后,我们需要提供完善的说明文档,给用户带来良好的使用体验。

今天着重实现上述的场景一过程, 在这一过程中我们一般有两种方案,一种是使用github Action结合官方npm 最后发布在公网中, 另一种是在企业内部实现制品库,发布在内网中。这里我使用腾讯的 Coding 的 devops 解决方案来实现内网发布。一来是可以更符合日常工作中的内部使用需求,再则可以规避掉起名的问题, 内网不会面临占包名的问题。

但是为了照顾到公网发布的情况下, 这里的制品库就更像是内网版的 npm 源。公网发布流程与下面的内容很相近,仅仅是无需将 npm 的源设置为 私人制品库的镜像源,保留使用 npm 官方源即可。

手动发布:

Coding 制品仓库:

账号注册:

首先, 我们需要去 coding官网 中去注册一个账号, 这个流程我就不过多赘述了,自行注册即可。

新建项目:

  点击左侧的目录栏, 选择项目,然后点击右侧的创建项目。

关联项目的仓库:

当然,你也可以直接创建一个新的仓库,可以将其视作一个私有版 git仓库。 这里我们已经有了 github 的仓库, 因此我们直接关联 github 即可。

可以选择不同 git 的相关方案,去选择鉴权方式,完成关联后,直接可以选择对应的仓库,还是蛮方便的。

创建制品仓库:

创建一个新的 NPM 制品仓库, 这个制品仓库就相当于 npm 官方的注册表的概念, 然后需要在本地设置对应的镜像源路径即可。

本地修改镜像源工具:

运行命令 pnpm i -g nrm 命令, 下载 nrm 用来管理包安装下载发布的源地址。

  • nrm ls: 查看所有的镜像源地址。
  • nrm add <registry name> <registry url> : 添加一个镜像源名称<registry name> 及对应的源的地址<registry url>
  • nrm use <registry name>: 修改当前正在使用的镜像源名称。

设置私人制品仓库地址:

  • 点击对应仓库的操作指引。

  • 查看其中最后两行:

  • 将制品仓库地址,设为你的镜像源地址。

    nrm add mini https://*********.net/mini-ui/ui
    
  • 然后运行nrm use mini , 切换镜像源,这里的名字和上面对应。

  • 运行 nrm ls , 查看当前使用的镜像源是不是私人制品库的 url

  • 然后运行下面的命令,然后根据你的 username 和 登陆密码进行登录。

    npm login
    
  • 可以运行 npm whoami 命令来检查是否登录成功。

本地设置发布脚本:

package.json文件修改:

具体的 package.json 每个字段的含义,大家可以自行去官网文档中查看,这里我主要是修改下面几项内容:

devDependencies:

  • 安装 np 用来完成整个发布的流程的对话式操作, 它会询问诸如 git工作区是否干净, 发布前清空 node_modules 并重新下载, 本次发布版本的更新选择(major.minor.patch)等流程问题。
  "devDependencies": {
    "tsup": "8.3.0",
    "esbuild-plugin-less": "1.3.9",
    "@types/react": "18.3.7",
    "@types/react-is": "18.3.1",
    "@types/lodash-es": "4.17.12",
    "np": "10.2.0"
  },

scripts/release

  • 通过在 monorepo 子包中建立 release 发布命令, 在 release 的命令中,分为三部分:首先打包整个 ui 子包,其次运行 np 命令(后面参数的含义是跳过测试、 发布)进入交互式问答, 最后运用 npm publish 发布整个包。
  • 跳过 测试、发布的原因是因为,我没有写测试的相关内容,会卡住流程, 跳过发布的原因是因为它自己去 ping 这个制品库,然后解析不出来主机名会报错。所以最后还是执行了一下手动发布的内容。
  • 其中下面 np 的配置是指清理node_modules 之后将 pnpm 作为包管理工具安装下载
// /packages/ui/package.json
{
    ...
    "scripts": {
        "dev": "tsup --watch",
        "build": "tsup",
        "release": "pnpm run build && np --no-tests --no-publish && npm publish"
    },
    "np": {
        "packageManager": "pnpm"
    },
    ...
}

files :

  • 通过 files 指定发布包时,上传的文件, 一般就是打包后的文件即可,注意不要把整个包都上传上去了。会导致包的体积过大。
  
  // /packages/ui/package.json
  "files": [
    "dist"
  ],

homepage : 这个包的官方地址,比如说明文档的地址。

repository: 记录仓库地址的相关信息。

根目录package.json 修改:

  • 通过增加 release:ui 脚本指令,调用 /packages/ui 子包的发布命令。
// /package.json
  "scripts": {

    "release:ui": "pnpm --filter=ui run release"
  },

测试:

  • 在根目录中,运行pnpm run release:ui指令,出现下面的内容:

    • 进行 ui 包中的打包指令:

    • 然后会让我选择一个更新的版本,其遵循semver 语义版本控制

    • 然后就是走流程,检查 git 工作区是否干净, 清空 node_modules 等一系列的流程。

    • 去 Coding 上查看制品库,这里就是已经发布两个版本了。

    • 新建一个项目,然后下载对应的包名 + 版本, 记得 nrm ls 查看源是否是配置的源, 最后 pnpm i @mini-ui/ui@1.0.2 完成组建库包的下载。

    • 在项目中引入对应的组件以及 css 文件:

      •     import './App.css'
            import { Button } from '@mini-ui/ui'
            import "@mini-ui/ui/dist/index.css"
        
            function App() {
              
              return (
                <div className='document'>
                  <Button type='primary'>123</Button>
                </div>
              )
            }
        
            export default App
        

自动化发布:

  • 点击项目下的 构建计划 子目录, 然后点击新增构建过程,选中自定义构建过程。

触发时机设置:

  • 点击构建计划,点击触发规则,然后通过正则匹配 github 推送的 tags 中以 v 开头的标签, 匹配命中后就执行流程。

  环境变量配置:

  • registry 制品库的地址, username以及password 这三个变量(在上文中获取到的制品库地址, 以及在 npm login 输入时的账号密码)存储在构建时的变量中,在流程中读取写入到 /packages/ui/.npmrc 文件,作为发布时的鉴权以及目标地址。

  

  流水任务设置:

  • 大致的流程就是, 当仓库提交了 v 开头的 标签后, 触发流水线, 检出仓库中的 main 分支, 然后我往 packages/ui/.npmrc 写入目标的制品仓库地址,登陆的账号密码(由于代码会提交到github中,因此没有作为配置文件写入)。 然后使用 node:22docker 镜像, 然后下载 pnpm, 通过 pnpm 下载所有的依赖, 然后运行 build 的命令, 最后进入到子包中发布。

    •     pipeline {
            agent any
            stages {
              stage('检出') {
                steps {
                  checkout([
                    $class: 'GitSCM',
                    branches: [[name: GIT_BUILD_REF]],
                    userRemoteConfigs: [[
                      url: GIT_REPO_URL,
                      credentialsId: CREDENTIALS_ID
                    ]]])
                  }
                }
                stage('写入环境变量') {
                  steps {
                    writeFile(file: 'packages/ui/.npmrc', text: """
                                registry=${npm_registry_url}
                                always-auth=true
                                //g-nwfy4597-npm.pkg.coding.net/mini-ui/ui/:username=${npm_username}
                                //g-nwfy4597-npm.pkg.coding.net/mini-ui/ui/:_password=${npm_pwd}""" )
                  }
                }
                stage('打包构建') {
                  agent {
                    docker {
                      reuseNode 'true'
                      registryUrl 'https://coding-public-docker.pkg.coding.net'
                      image 'public/docker/nodejs:22-2024.08'
                      args '-v /root/.npm:/root/.npm'
                    }
      
                  }
                  steps {
                    echo '自定义构建过程开始'
                    sh 'npm i pnpm -g && pnpm i && pnpm run build:ui'
                    sh 'cd packages/ui && npm publish --registry="$npm_registry_url"'
                  }
                }
              }
            }
      

测试

  • 注意:package.json 中version也需要修改

总结:

首先我们使用手动发布,尝试了整体的发布流程,然后我们又通过自动化的流水线, 实现每次发版 v 开头的标签时, 就会触发部署,发布最新的 npm 包。当然如果是在开源的场景下,也可以通过 github Action 完成相关的自动化流程。