自动化部署
前端部署的本质:把构建产物发布到可访问的环境。从手动 SCP 到全链路 CI/CD,本质是让流程可重复、可回滚、可观测。
一、CI/CD 是什么
- CI(Continuous Integration):代码合并后自动跑构建、测试、lint
- CD(Continuous Deployment/Delivery):自动把构建产物发布到对应环境
二、流程设计
1. 环境分层
| 环境 | 用途 | 触发方式 |
|---|---|---|
| dev | 开发者本地 | 手动 |
| test / uat | 测试联调 | merge 到 develop 自动 |
| staging | 预发,灰度前最后一道 | merge 到 release/* |
| production | 线上 | 打 tag 自动 + 人工确认 |
2. 标准流水线
代码 push → 安装依赖 → lint → 单测 → 构建 → 产物上传(OSS/CDN)→ 通知
三、GitHub Actions 实战
.github/workflows/deploy.yml:
name: Deploy
on:
push:
branches: [main, develop]
tags: ["v*"]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: 设置 Node
uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm
- name: 安装依赖
run: pnpm install --frozen-lockfile
- name: Lint
run: pnpm lint
- name: 单元测试
run: pnpm test -- --ci
- name: 构建
run: pnpm build
env:
NODE_ENV: production
APP_VERSION: ${{ github.sha }}
- name: 上传到 OSS
uses: fangbinwei/aliyun-oss-upload-action@v1
with:
accessKeyId: ${{ secrets.OSS_KEY_ID }}
accessKeySecret: ${{ secrets.OSS_KEY_SECRET }}
bucket: my-bucket
source: dist
destination: prod/${{ github.sha }}/
- name: 刷新 CDN
run: |
curl -X POST "https://cdn.aliyuncs.com/refresh" \
-H "Authorization: ${{ secrets.CDN_TOKEN }}" \
-d "path=/prod/${{ github.sha }}/index.html"
四、Jenkinsfile 简版
pipeline {
agent any
stages {
stage('Install') { steps { sh 'pnpm install' } }
stage('Test') { steps { sh 'pnpm test' } }
stage('Build') { steps { sh 'pnpm build' } }
stage('Deploy') {
steps {
sh 'rsync -avz dist/ user@server:/var/www/app/'
}
}
}
post {
success { slackSend(channel: '#deploy', message: '部署成功') }
failure { slackSend(channel: '#deploy', message: '部署失败') }
}
}
五、部署策略
| 策略 | 说明 | 适用 |
|---|---|---|
| 全量发布 | 一次性替换所有机器 | 内部系统、低风险 |
| 灰度发布 | 按比例放量(1% → 10% → 50% → 100%) | 通用 |
| 蓝绿发布 | 切流量,旧版保留回滚 | 重要业务 |
| A/B 测试 | 多版本共存,按用户分流 | 产品验证 |
前端最常用的是灰度 + 静态资源版本化:用 HTML 文件名带 hash,每次发版保留旧版本在 CDN,回滚只需要把入口 HTML 切回旧版本。
六、产物的版本管理
- 入口 HTML:
/index.html(不带 hash,可被覆盖) - 静态资源:
/static/js/app.[contenthash].js(带 hash,永久缓存) - 回滚方案:保留最近 3 个版本的目录,出问题直接改入口指向
cdn-root/
├─ v1.2.0/
│ ├─ index.html
│ └─ static/
├─ v1.2.1/
│ └─ ...
└─ v1.2.2/
└─ ...
七、避坑指南
- source map:生产环境不要上传到公网,会暴露源码;可上传到 Sentry 私有服务
- 环境变量:CI 里用
secrets注入,不要写死在代码里 - 缓存依赖:CI 启用依赖缓存(pnpm/npm/yarn cache),能省一半时间
- 构建可复现:固定
package-lock.json,加--frozen-lockfile - 回滚优先于修复:线上故障先回滚,修复永远没有回滚快
- 构建结果归档:把每次构建的产物归档到 OSS/对象存储,保留至少 7 天
八、面试高频
- Q:前端发版如何做到秒级回滚? A:入口 HTML 不带 hash 走 CDN,每次发版保留旧版本目录,回滚时把入口指回旧版本即可,无需重新构建。
- Q:CI 和 CD 的区别? A:CI 关注代码集成后的自动验证(构建、测试、lint);CD 关注把验证通过的产物自动发布到对应环境。
- Q:灰度发布怎么实现? A:按用户 ID / 设备 ID 哈希到不同版本,先放 1% 流量观察监控指标,OK 再逐步放量。