看了它!你也能轻松部署vue3组件库

1,081 阅读8分钟

开发组件库场景

作为前端开发人员,当你运行一个 npm install element-plus -S,会安装 element-plus,打开 node_modules 能看到它对应很多相关联的依赖包,通过 app.use(ElementUI),我们可以很方便的在全局使用 element 提供的组件,在官网上复制一串代码,就可以实现已经写好的组件效果,是不是非常的爽?

有没有想过这是如何实现的,曾几何时我也在想为什么这样就可以直接用,这是什么原理?读了这篇,你就会恍然大悟,我也可以自己造一个组件库轮子自己用。

但是,人家写好的组件毕竟不是定制化的,可能每个公司都有自己的主题、风格,所以类似写好的组件库也需要自己根据设计图或者要求进行二次封装才能达到预期效果。那么,如何才能更少的修改代码甚至不用改代码就能实现预期的 UI 样式呢?

答案就是根据自己公司的主题、样式开发维护一个自己的组件库,然后只需要复制粘贴就可以实现效果,一想到这样,嘴角不禁忍不住上扬。

本篇文章就是讲解一下如何用建木 CI 快速部署自己的组件库到 npm 仓库,本着提倡追逐新技术的原则,当然要选择用前沿的前端架构以及技术,所以用 vue3+typescript+vite+gulp+rollup 等技术栈来开发组件库,采用 monorepo 的模式来开发组件库,包管理工具我们这里用 pnpm,因为它对这种 workspace/**多工作目录有着更好的支持。

采用 monorepo,后续也可以把组件库文档项目也融合在里面,实现组件库和文档统一编写和部署。

采用建木 CI 可以实现持续集成、持续交付、持续部署,这令前端组件库可以快速更新。

首先,需要清楚,我们要干嘛,有哪些事情要做,怎么把它们串联起来,形成一个完整的闭环。我们先来看看不同的模式。

概念介绍

相信大家可能听说过monorepomultirepo两个名词,但是不一定所有同学都知道这两个词的含义,先解释一下:

  • 一个项目,建立一个代码仓库,单独管理、开发、提交推送和部署,这种方式就称之为multirepo
  • 反过来,把多个项目放到同一个代码仓库管理,就称之为monorepo。包括 vue3、babel、react 在内的众多国内外著名的项目都采用了这种方式。

由以上解释说明monorepomultirepo就是两种不同的代码组织管理方式,分别对应着“合”和“分”两种设计哲学。

第一种 手动发布(multirepo,所有代码都在一个项目文件夹中,全部一起发布):

  • 创建一个 vue3+ts 组件库项目,关联 gitee 远程仓库。
  • 安装需要的插件,修改其配置文件(构建、运行、部署)。
  • 编写并 push 代码(发版前的那次 push 需要修改版本号)。
  • 手动发版(在本地 build,进入 dist 目录进行发布或执行提前定义好的发版脚本)。

第二种 采用建木 CI 发布(monorepo,components、hook、utils、docs、theme-chalk…为单独项目可单独发布):

  • 创建一个 vue3+ts 组件库项目,用 pnpm 初始化配置,关联 gitee 远程仓库。
  • 安装需要的插件,修改其配置文件(构建、运行、部署),修改项目结构为 monorepo 模式。
  • 编写推送代码,编写建木 CI 流程,CI 生成的 webhook 与 gitee 仓库关联。
  • 远程仓库上打 tag,webhook 触发建木流程,发布成功。

以上两种模式,各有优点,手动部署采用单项目适合开发人员少的项目,开发维护人员少的情况,简单快速。由于建木是开源项目,涉及到的人员会很多,采用第二种更加适合,毕竟大家一起提 issues、pr 能更加使一个项目趋近于成熟,所以本文采用第二种。

创建初始化项目

前面提到 monorepo,我们需要用 pnpm 管理项目,所以我们先全局安装一下 pnpm,别担心,和 npm 命令差不多:

npm install -g pnpm
// or
yarn global add pnpm

查看 pnpm 版本:

pnpm -v
// 6.32.4

我们需要先准备一个前端项目。本文将使用最近前端圈较火的 vite 来生成一套 vue3+ts 的代码。

vite 官网:vitejs.cn/

打开编辑器,终端输入:

# pnpm创建项目方式\
pnpm create vite jianmu-ui -- --template vue-ts

(为了使用 monorepo)安装依赖前,我们先在项目根目录下创建.npmrc 文件。(输入 shamefully-hoist=true)

终端输入 cd jianmu-ui 进入项目根路径,执行下面命令接着为项目安装依赖。

cd jianmu-ui

vim .npmrc

shamefully-hoist=true
:wq #保存退出

cat .npmrc
shamefully-hoist=true

pnpm install

让项目跑起来看看效果吧!执行下面命令(具体 script 指令,详见项目下的 package.json)。

pnpm dev

浏览器输入 http://localhost:3000 看见下面的页面说明一个简洁的 vue3 项目已经搭建好了。

接下来,我们先 control + C 停止项目,让我们对这个项目做一些改造,成为一个真正的 monorepo 架构的组件库项目。

删除 src、public 目录,删除 index.html、tsconfig.node.json、vite.config.ts。

用以下代码覆盖 tsconfig.json:

{
  "extends": "@vue/tsconfig/tsconfig.web.json",
  "compilerOptions": {
    "allowJs": true,
    "module": "esnext",
    "target": "es6",
    "noImplicitAny": false,
    "declaration": true,
    "sourceMap": true,
    "lib": ["es6", "DOM", "DOM.Iterable"],
    "allowSyntheticDefaultImports": true,
    "types": ["unplugin-vue-define-options"]
  },
  "include": ["packages", "typings"],
  "exclude": ["node_modules", "**/dist"]
}

此时会报错,项目根目录执行以下命令。

# -W 是确认安装在根目录下 安装之后还是报错,可以重新用编辑器打开项目加载代码
pnpm install @vue/tsconfig unplugin-vue-define-options -D -W

根目录下创建文件夹 packages、play、build 三个,packages 用来放组件库的源代码、组件、工具类、样式等,而 play 目录则是使用我们写好的组件(预览),build 则是放打包命令相关的代码。 还需要创建一个 pnpm-workspace.yaml 文件,指定我们的工作目录,内容如下:

packages:
  # all packages in subdirs of packages/ and components/
  - "packages/**"
  # exclude packages that are inside test directories
  - "play"
  - "build/*"

此时你的项目结构应该像这样:

后面就是一些关于本组件库打包配置的编写,由于本篇重点在于如何用建木 CI 发布前端写好的项目,故不再赘述项目的一些配置编写,会着重讲解后面建木 CI 发版的流程,后续单写一篇文章详细说明组件库项目配置的编写。

下面我们需要在建木 CI 里面,创建项目(自动构建发版我们开发的组件库),如何安装建木 CI 以及详细信息,可以参考建木 CI 官方文档:建木 CI 快速开始。 只需要将下面的 dsl 流程拷贝至建木 CI 中等待流程跑通。gitee 上的 jianmu-ui 仓库中的前端代码将会被自动 clone 下来,并且将 build 后生成的 dist/jm-plus 文件夹中的项目通过官方 npm 发布依赖包节点 发布到 npm 上。

(下面 dsl 注意: 在使用官方节点的时候,git_clone 节点需要传用户和密码,在建木 CI 密钥管理处添加上命名空间 gitee,加上你的用户和密码即可,npm_publish 节点需要去登录 npm 官网,生成一个 public 类型的 token,同样在密钥管理处添加命名空间 npm 下面再添加生成的 token)。

gitee 密钥:

在 npm 官网获取 token:

npm 密钥:

组件库发布流程 dsl:

name: 发布建木UI库
description: 拉取代码,执行pnpm install,pnpm build,进入dist目录后npm publish发布

trigger:
  type: webhook
  param:
    - name: gitee_token
      type: SECRET
      exp: $.header.X-Gitee-Token
    - name: gitee_event
      type: STRING
      exp: $.header.X-Gitee-Event
    - name: gitee_tag_created
      type: BOOL
      exp: $.body.json.created
    - name: gitee_ref
      type: STRING
      exp: $.body.json.ref
    - name: project_name
      type: STRING
      exp: $.body.json.project.path
    - name: project_url
      type: STRING
      exp: $.body.json.project.url
    - name: author_name
      type: STRING
      exp: $.body.json.head_commit.author.name
    - name: author_url
      type: STRING
      exp: $.body.json.head_commit.author.url
    - name: commit_msg
      type: STRING
      exp: $.body.json.head_commit.message
  only: (${trigger.gitee_event} === "Tag Push Hook" && ${trigger.gitee_tag_created})

pipeline:
  git_clone:
    type: git_clone:1.2.0
    param:
      remote_url: https://gitee.com/wllgogogo/jianmu-ui.git
      ref: ${trigger.gitee_ref}
      username: ((gitee.wjg_username))
      password: ((gitee.wjg_password))
  nodejs_build:
    alias: 构建UI组件库
    image: node:16.14.2-alpine3.14
    environment:
      workspace: ${git_clone.git_path}
      gittag: ${git_clone.git_tag}
      registry_url: https://registry.npmmirror.com/
    script:
      - set -e
      - cd ${WORKSPACE}
      - yarn config set registry ${REGISTRY_URL} && yarn config get registry
      - yarn global add pnpm@6.32.4
      - pnpm -v
      - pnpm config set registry ${REGISTRY_URL}
      - pnpm install
      - pnpm run build
  npm_publish:
    alias: 发布npm依赖包
    type: npm_publish:1.0.0-16.13.0
    param:
      workspace: ${git_clone.git_path}/dist/jm-plus
      npm_user_token: ((npm.wjg_token))
      version: ${git_clone.git_tag}
  feishu_nodtice_pr_assignee:
    alias: 飞书通知发布UI库
    type: feishu_notice_interactive:1.0.4
    param:
      bot_webhook_url: ((feishu.webhook_url))
      msg_title: 建木UI发布通知
      msg_markdown: "**PUBLISH**:[${trigger.project_name}](${trigger.project_url})\n**描述**: ${trigger.commit_msg}\n**创建人**:[${trigger.author_name}](${trigger.author_url})\n**UI组件**: [${npm_publish.package_name}](https://www.npmjs.com/package/${npm_publish.package_name})\n**版本**: ${git_clone.git_tag}"

创建项目后,建木 CI 会生成一个 webhook 链接,点击查看可复制。

  • 需要注意的是,你的 URL 地址需要是公网 ip 或者域名(内网 ip 会报错)

把刚刚复制的 webhook 链接地址粘贴到图中所示,这里我们选择 TAG Push 事件触发,点击添加:

接下来我们只需要,创建标签,触发发布流程就行了(标签即版本,不能与已发版的版本重复,不然会报错):

回到建木 CI 可以看到,流程正在执行,不一会就自动发版成功并且会接收到通知:

我们打开 npm 官网,搜索 jm-plus 也可以看到我们刚刚发版成功的组件库的版本了,接下来我们就可以愉快的在前端项目里执行npm install jm-plus -S,来使用我们开发的组件库了。

本文为建木博主「wllgogogo」的原创投稿文章,转载请联系授权。

项⽬官⽹:jianmu.dev

项⽬托管:gitee.com/jianmu-dev

项⽬文档:docs.jianmu.dev