前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版

Jenkins 部署微前端实践总结,从构建到上线全链路

首页2021-11-17 10:35:08Front-End
微前端Jenkins持续集成CI/CD部署阿里云OSS

微前端把一个仓库拆成一个主应用加七八个子应用之后,本地开发是舒服了,发布这件事却变得很尴尬。全量构建一次要十几分钟,可这次上线明明只改了一个子应用。手动打包再 scp 上去也不是办法,子应用要放进主应用目录下的固定子目录,主应用发布时还不能把这些子目录删掉。

这篇把我用 Jenkins 跑微前端流水线的整套配置写下来,包括按需构建哪几个包、构建产物怎么归拢、构建后 shell 怎么在部署机上做「主应用覆盖但保留子目录」这个动作,最后再补一条阿里云 OSS 加 CDN 的路子和一份上线前 checklist。

在本篇文章中,我们将从浅入深,和大家一起学习以下知识:

  • 微前端从提交代码到用户看到页面,整条链路都发生了什么
  • Jenkins 的系统管理、凭据、插件、视图、任务这几个概念怎么对上
  • 参数化构建怎么配,才能做到「只构建勾选的那几个包」
  • 构建 shell 和构建后 shell 的完整代码,以及每一段在防什么坑
  • 主应用发布时怎么不误删子应用目录
  • 换成阿里云 OSS 加 CDN 部署要配哪几步,index.html 的缓存怎么设
  • 一份可以直接抄的上线前 checklist

# 一、先把整条链路画出来

配置界面点来点去很容易迷路,动手之前先把链路捋一遍,后面每一个配置项落在哪一步就清楚了:

   开发提交代码
        │
        ▼
┌───────────────────────────────────────────┐
│  Jenkins 构建机                            │
│                                           │
│  ① General                                │
│     参数化:mutiParams(勾哪几个包)       │
│              isRunInstall(要不要装依赖)  │
│  ② 源码管理  Git plugin 拉代码             │
│     → /var/lib/jenkins/workspace/{任务名}  │
│  ③ 构建  执行 shell                        │
│     for 勾选的包: npm install → npm build  │
│     产物统一搬到 publish/{子目录}          │
└──────────────────┬────────────────────────┘
                   │ ④ Send build artifacts over SSH
                   │    publish/** → 部署机
                   ▼
┌───────────────────────────────────────────┐
│  部署机                                    │
│  ⑤ Exec command(构建后 shell)            │
│     main  → 铺到部署根目录(保留子目录)    │
│     subs/* → 各自覆盖到同名子目录          │
│     最后删掉 publish 临时目录              │
└──────────────────┬────────────────────────┘
                   │
                   ▼
        Nginx 指向部署根目录 / 或 OSS + CDN
                   │
                   ▼
              用户访问页面
@前端进阶之旅: 代码已经复制到剪贴板

整条链路的难点只有一处,就是第 ⑤ 步。主应用的产物要铺在部署根目录下,子应用的产物在同一个根目录下各占一个子目录,那主应用重新发布时,怎么在清掉旧文件的同时不把子应用目录一起删了。后面第四节的 shell 就是在解决这件事。

如果你还不清楚主应用和子应用在运行时是怎么互相找到的,可以先看 微前端实战总结,从 single-spa 到 qiankun 的原理拆解,那边讲的是原理,这篇只讲上线。还没定下来用哪套框架的话, 微前端落地方案对比,qiankun 无界 Module Federation 怎么选 里有一条可以照着走的选型路径。

顺便说一句,下面这套流水线其实和你用哪个微前端框架关系不大。不管是 qiankun 还是 icestark,产物都是一堆静态文件,差别只在目录怎么摆。

# 二、Jenkins 的几个概念先对齐

Jenkins 是基于 Java 开发的持续集成工具,免费开源,用于监控持续重复的工作,目标是把软件的持续集成自动化。功能上主要是两块,持续的软件版本发布和测试,以及监控外部调用执行的工作。

它的界面概念不多,但名字起得有点绕,先花几分钟对齐一下。

# 2.1 系统管理

执行者数量是系统可同时并发执行任务的数量,默认 2 个。这个值原则上不要超过服务器 CPU 核数,否则容易出现 CPU 过载把服务拖挂。微前端项目一次构建可能同时跑好几个 npm run build,本来就吃 CPU,这里我一般不往上调。

Jenkins URL 是 Jenkins 的访问地址,改这里的端口号和改服务器配置文件的端口号效果一致。

凭据用来存储需要密文保护的东西,数据库密码、GitLab 密码、Docker 私有仓库密码都放这儿,Jenkins 靠它和第三方应用交互。要安装 Credentials Binding 插件用户才能管理凭据。凭据管理包含凭据本身和凭据所在域的管理,系统默认会创建全局域,你也可以自己添加域再在域下加凭据。为了最大程度提高安全性,在 Jenkins 中配置的凭据以加密形式存储在主实例上,由 Jenkins 实例 ID 加密,使用时靠配置的唯一标识 ID 引用。

可以添加的凭据有五种:用户名和密码、SSH 密钥(SSH 公私钥对)、加密文件、令牌(例如 API 令牌、GitHub 个人访问令牌)、证书。添加时要填种类、范围(全局或系统)、凭据内容、ID、描述。

这里有个坑要注意,ID 字段是可选的,不填 Jenkins 会分配一个全局唯一的 GUID。但一旦设置了凭证 ID,之后就无法再更改。所以如果你打算在 Pipeline 脚本里按 ID 引用凭据,第一次就把名字起对。

插件管理有两条路。一条是在管理平台界面里用插件管理器,路径是「系统管理」→「插件管理」,在「可选插件」标签下搜索需要的插件,勾选后点左下角的下载并重启后安装,等下载完成服务自动重启,重新进入系统即安装成功。另一条是用 Jenkins CLI 的 install-plugin 命令,适合用脚本或者配置管理代码来装插件的场景,不需要在 Web UI 里做人工交互。

用户管理默认使用自带数据库模式存储用户,Jenkins 默认创建 admin 账号,初始密码在 /var/lib/jenkins/secrets/initialAdminPassword,登录之后可以在管理用户里改掉。第一次装完记得改,这个文件路径是公开的常识。

# 2.2 视图和任务

视图主要用来管理不同项目之间的任务,一般是每个项目建一个视图,在视图下管理整个项目的模块。常用的是列表视图(显示简单列表,新建或编辑视图时可以把已有任务加进来,也可以在该视图下新建任务)和我的视图(自动显示当前用户有权限访问的任务)。

新建任务时要填任务名称,选任务模板。新装的 Jenkins 一般只有一个「构建一个自由风格的软件项目」模板,其他模板要下对应的插件,不同模板的构建流程也不一样。还有个复制选项,输入已有任务名可以复制一份新任务,但选了复制就不能再自定义模板了,会以被复制项目的模板为准。

任务详情页里几个常用入口:状态、修改记录(每次构建获取的代码变更记录,也就是这次构建的 git 提交记录)、工作空间(任务的项目文件目录)、立即构建、配置(配置整个构建和部署过程要干什么)、删除工程、重命名。

概念就这些。下面进入正题,一步步配任务。

# 三、任务配置分四步走

任务配置就是把「从拉代码到部署成功」这个过程拆成几段分别配置。

# Step 1. General

这一步是执行构建前对 Jenkins 本身做的一些设置。

丢弃旧的构建默认策略是 Log Rotation,可以设保持构建的天数(保存此天数内的构建记录,为空则全保留)和保持构建的最大个数(保存最近这么多次构建,为空则全保留)。这两个建议一定要设,构建产物加上工作空间很吃磁盘,我见过因为没配这个把构建机磁盘塞满的。

参数化构建过程是微前端场景下最关键的一项,它就是「只构建我勾选的那几个包」的实现方式。

要装 Extended Choice Parameter 插件,它提供多选框类型的参数:

Extended Choice Parameter 插件安装界面

配置项逐条对应关系是这样:

  • Name:构建过程使用的参数名,后面 shell 里靠这个名字取值
  • Description:参数描述
  • Parameter Type:Check Boxes,也就是多选框
  • Number of Visible Items:8,checkbox 参数值个数,等于项目子包和主包的总数
  • Delimiter:,,各个值的分割符号
  • Choose Source for Value:main,subs/appletuser,subs/college,subs/follow,subs/project,subs/questions,subs/statistics,subs/system,填的是主包和子包相对项目根目录的路径
  • Choose Source for Default Value:同上,表示默认全选

这里的取值一定要写成相对项目根目录的路径,因为构建 shell 里会直接 cd 进去。写成应用名而不是路径的话,shell 里还得再做一次映射,没必要。

另外再加一个布尔值参数,用来判断这次构建要不要跑 npm install:

  • 名称:isRunInstall
  • 默认值:默认是否勾选
  • 描述:参数描述

依赖没变的日常发版把它关掉,能省下好几分钟。这个开关是全局的,勾选的所有应用会按同一个规则执行。

# Step 2. 源码管理

用 Git plugin 同步代码仓库。任务执行时代码会被拉到 /var/lib/jenkins/workspace/{任务名称} 目录下,后面 shell 里的 $WORKSPACE 环境变量就是这个路径。

要填的东西不多:

  • Repository URL:代码仓库地址
  • Credentials:服务器连接代码仓库的凭据,可以在系统管理里加好后在这选,也可以点右边的添加按钮现加,新增方式和系统管理里一样
  • Branches to build:指定任务需要拉取的分支,允许配多个
  • 源码库浏览器:指定 git 仓库类型,默认自动

# Step 3. 构建

执行 shell 这一步,源码管理插件已经把代码拉下来了。这段 shell 要做的是按参数化构建时勾选的应用逐个打包,再把产物统一放到项目根目录的 publish 文件夹里。

#!/bin/bash
# 项目根目录地址(相对于工作空间)
project_path=""
# 将用户选择需要打包的应用拆分成数组
OLD_IFS="$IFS"
IFS=","
arr=($mutiParams)
IFS="$OLD_IFS"
# 清空上次打包的部署文件
rm -rf $WORKSPACE$project_path/publish


for i in ${arr[@]}
do
    # 进入对应的应用中执行打包过程,$WORKSPACE为系统环境变量,值为工作空间地址
    cd $WORKSPACE$project_path/$i
    rm -rf dist
    # 判断是否需要执行环境安装,当前设置为全局设置,所有需要打包的应用会执行相同的判断
    if [[ $isRunInstall == "true" ]]
    then
      npm install
    fi
    npm run build
    # 将子应用和主应用放在同一级,便于后续部署,因为很多微前端项目子应用都会放置在同一个文件夹下
    [[ $i == "main" ]] && subdir=$i || subdir=${i##*/}


    mkdir -p $WORKSPACE$project_path/publish/$subdir
    mv dist/* $WORKSPACE$project_path/publish/$subdir
done
@前端进阶之旅: 代码已经复制到剪贴板

拆开看几处关键的。

fe
  • 一、先把整条链路画出来
  • 二、Jenkins 的几个概念先对齐
    • 2.1 系统管理
    • 2.2 视图和任务
  • 三、任务配置分四步走
    • Step 1. General
    • Step 2. 源码管理
    • Step 3. 构建
    • Step 4. 构建后操作
  • 四、跑一次构建看看结果
    • 4.1 构建前
    • 4.2 构建后
  • 五、完整配置走一遍
    • 5.1 需要装的三个插件
    • 5.2 配好之后长什么样
    • 5.3 配置流程截图
    • 5.4 构建的 shell 代码
    • 5.5 构建后操作的 shell 代码
  • 六、换一条路,阿里云 OSS 加 CDN
    • 6.1 创建 Bucket 存储桶
    • 6.2 添加 CDN 域名
    • 6.3 添加 CNAME 记录
    • 6.4 设置存储桶
    • 6.5 上传代码
  • 七、上线前 checklist
  • 总结
  • 参考

← Git开发流程分支管理方案实战梳理Serverless 架构与微信小程序云开发实践总结 →