前端 CI/CD 通常包含哪些流程?
简化版
前端 CI 通常完成可复现安装、格式与 Lint、类型检查、测试、安全扫描和生产构建;CD 将同一份版本化产物按审批、灰度、健康检查和监控发布,并保留快速回滚能力。核心不是堆步骤,而是保证同一提交得到可追踪、不可变且验证过的产物。
详细版
流水线一般是:检出固定 commit,锁定 Node 与包管理器,按 lockfile 安装,执行质量 Gate,构建并生成制品、清单、Source Map 和校验值。构建成功后把制品上传制品库,再由部署阶段推广到测试、预发和生产,避免每个环境重新构建。
静态站发布应先上传带 hash 的 JS/CSS,再切换引用它们的 HTML,并保留旧资源。灰度阶段关注错误率、核心接口成功率和 Web 指标;异常时回退入口或路由到上一版本。
密钥只通过 CI 的 secret 管理按最小权限注入,不能写进日志或前端 bundle。缓存用于加速,不应改变构建结果,cache key 要包含 lockfile、Node 和工具版本。
完整版教学
一、CI 与 CD 分别控制什么风险
CI 解决多人频繁合并后的质量不确定性:每个候选提交都用同一命令检查。CD 解决“验证过的代码怎样安全到达用户”,包括审批、环境推广、灰度、观测和回滚。
| 阶段 | 输入 | 输出 | 失败后动作 |
|---|---|---|---|
| CI | commit + lockfile | 验证过的制品 | 禁止合入/发布 |
| 交付 | 已签名制品 | 可部署版本 | 保留待审批 |
| 部署 | 指定版本 | 线上流量 | 暂停或回滚 |
心法:一次构建、多次推广;发布的是制品,不是在生产机上重新碰运气构建源码。
二、可复现安装为什么是第一道 Gate
如果 CI 用宽松安装重新解析依赖,今天和明天可能得到不同的间接版本。应提交唯一包管理器的 lockfile,固定 Node/包管理器版本,并使用对应的冻结安装命令。
以 npm 为例,npm ci 要求 lockfile 存在且与 package.json 匹配,不匹配就失败,并且不会改写清单。若生成 lockfile 时使用会影响依赖树的特殊参数,CI 也必须保持一致。
缓存的是下载内容或可安全复用的构建中间物,不是跳过依赖一致性校验。一个合理 cache key 至少包含操作系统、Node 主版本和 lockfile 摘要,lockfile 改动时应自然失效。
三、质量 Gate 如何排序才能快速失败
便宜且高命中的检查应靠前,例如格式、Lint 和类型;较慢的单元、集成、端到端测试可并行。最后才做生产构建和体积预算,减少错误提交占用大量计算资源。
install → format/lint/type ─┬→ unit
├→ integration
└→ security scan
全部通过 → build → artifact
假设串行耗时为 2+3+6+8+5=24 分钟,把互不依赖的 6、8、5 分钟任务并行后,关键路径约为 2+3+8=13 分钟。实际还要加队列和制品传输时间,但并行收益可量化。
四、制品为什么要不可变并带身份
产物应绑定 commit SHA、构建号和版本,生成完整性校验值,并保存 Source Map 与依赖清单。部署环境只选择某个已经验证的 artifact,不再次运行 npm install && build。
若测试环境构建 A、生产环境重新构建 B,即使源码 commit 相同,依赖、时间戳或环境参数也可能不同,测试结论无法完整覆盖生产。确需环境差异时,优先运行时配置,并记录配置版本。
Source Map 可以上传监控平台而不公开部署,release 必须与错误事件一致。否则线上 app.abc.js:1:200 可能被错误映射到另一版本源码。
五、前端静态资源的安全发布顺序
内容 hash 资源可长期缓存,HTML 是指向这些资源的入口。先发布 HTML、后上传资源会出现窗口期 404;先上传资源、确认可访问,再切 HTML 更安全。
1. 上传 app.newhash.js / css
2. 探测资源可访问且校验一致
3. 发布引用 newhash 的 HTML
4. 灰度观察
5. 延迟清理旧 hash 资源
旧页面可能在数小时后才动态加载旧 chunk,所以不能部署后立即删除历史资源。回滚通常只需把 HTML 或入口路由切回旧版本,前提是旧制品和资源仍被保留。
六、灰度、观测与回滚闭环
发布成功不等于进程返回 0。应先让 1% 或一个内部群体访问,比较错误率、接口失败率、LCP/INP 和关键业务转化,再逐步扩大流量。
假设基线错误率为 0.20%,新版本灰度 10,000 次会话出现 80 次错误,错误率为 0.80%,是基线的 4 倍,应触发暂停或回滚。阈值还需结合样本量和业务风险,不能只看绝对错误数。
回滚脚本应和发布脚本一样被演练。数据库或服务端接口若有不兼容变更,单独回退前端未必有效,因此跨端发布要采用向后兼容、分阶段启用的策略。
发布凭证与供应链边界
构建任务通常只需读取依赖和写入制品库,生产部署凭证应放在受保护的部署阶段,不能让所有 PR 流水线获得。第三方贡献分支尤其不能直接读取生产 secret,否则一段恶意构建脚本就可能外传凭证。
依赖安装期间还可能执行生命周期脚本,因此锁住版本不等于代码可信。高风险项目应结合来源审查、最小网络权限、制品签名与 SBOM,让发布链条能回答“谁构建、用了什么、谁批准”。
七、常见误区与追问
- 误区:CI 能构建成功就可以直接全量发布。 构建只验证产物生成,还需要部署检查、灰度和线上观测。
- 误区:每个环境重新构建更灵活。 它会让验证产物与生产产物不一致,应优先推广同一制品。
- 误区:带 hash 的资源发布后可以立刻删除旧版本。 旧会话和动态导入仍可能引用旧 hash。
- 追问:前端流水线为什么先上传静态资源再发布 HTML? 新资源提前存在不会影响旧页,反向顺序却会让新 HTML 请求 404。
- 追问:缓存怎样做到只提速、不破坏正确性? cache key 纳入平台、工具版本和 lockfile,未命中时仍能完整构建。
- 追问:密钥怎样进入流水线? 通过受控 secret 存储按环境和最小权限注入,并避免日志与前端产物泄露。
- 追问:前端回滚的必要条件是什么? 版本化不可变制品、旧资源保留、可切换入口以及后端兼容。
八、加强记忆
用“锁、验、产、发、观、退”串起流水线:锁定运行时和依赖,快速验证质量,只构建一次不可变制品,按正确资源顺序灰度发布,用真实指标观察,异常时切回已保留版本。这个闭环比罗列十条命令更能体现 CI/CD 的可靠性交付目标。