Files
张翔 8840c4398a feat: downgrade tech stack to stable versions and integrate GA4 error monitoring
- Downgrade Next.js 16→14.2, React 19→18.3, Tailwind 4→3.4
- Add comprehensive GA4 error monitoring system
- Create Jenkins CI/CD pipeline with quality gates
- Fix build issues: ESLint, SWC conflict, config format
- Add documentation for deployment and error tracking
2026-05-12 12:45:18 +08:00

616 lines
20 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Novalon Website 回滚流程指南(生产环境专用)
> **最后更新**: 2026-05-12
> **适用项目**: novalon-website (四川睿新致远科技有限公司官网)
> **部署架构**: 静态导出 + Docker + Nginx + CDN
> **目标恢复时间**: < 10 分钟(P0 级别故障)
>
> **⚠️ 重要提示**:本文档已针对你的实际部署环境定制,请勿使用通用模板!
---
## 📋 你的实际部署架构
```
┌─────────────────────────────────────────────────────┐
│ 开发机 (Local) │
│ - 项目路径: /Users/zhangxiang/Codes/Novalon/ │
│ novalon-website │
│ - 构建命令: npm run build:clean │
│ - 输出目录: dist/ │
│ - 部署命令: ./deploy-dist.sh │
└──────────────────────┬──────────────────────────────┘
│ rsync + SSH (root@139.155.109.62)
┌─────────────────────────────────────────────────────┐
│ 生产服务器 (139.155.109.62) │
│ └── /home/novalon/docker-app/ │
│ ├── novalon-static/ ← 当前版本 │
│ ├── novalon-static_backup_* ← 自动备份 │
│ └── docker-compose.yml │
│ └── novalon-nginx-secure ← Nginx 容器 │
└──────────────────────┬──────────────────────────────┘
│ 反向代理
┌─────────────────────────────────────────────────────┐
│ 用户访问 │
│ - 主域名: https://novalon.cn │
│ - 备用 IP: https://139.155.109.62 │
│ - HTTP → HTTPS 自动跳转 │
└─────────────────────────────────────────────────────┘
```
---
## 🚨 **触发条件(满足任一即启动回滚)**
### **P0 - 紧急故障(立即回滚,无需审批)**
- [ ] 首页完全白屏或返回 500/502/503/504
- [ ] 所有页面无法访问(HTTP 状态码非 200)
- [ ] 安全漏洞报告(XSS、数据泄露、恶意重定向)
- [ ] 域名解析失败或 SSL 证书过期
### **P1 - 严重问题(30 分钟内回滚)**
- [ ] 核心功能不可用:
- 导航栏无法点击
- 表单提交失败(联系表单、订阅等)
- 主题切换失效
- 移动端布局错乱
- [ ] 关键 SEO 元数据丢失:
- `<title>` 为空或显示 "Untitled"
- `<meta name="description">` 缺失
- Open Graph / Twitter Card 标签缺失
- [ ] 性能严重退化:
- Lighthouse Performance < 50(之前 > 90
- LCP (Largest Contentful Paint) > 5 秒
- FID (First Input Delay) > 300ms
### **P2 - 一般问题(24 小时内修复)**
- [ ] 次要页面样式异常(不影响核心功能)
- [ ] 图片资源加载失败(非首屏图片)
- [ ] 控制台有警告但无错误
---
## 🔄 **Type 1:代码回滚(最常用,推荐首选)**
### **适用场景**
- 最近一次部署引入了 bug
- 需要快速恢复到上一个稳定版本
- Git 历史清晰,可以定位到稳定的 commit
#### **Step 0:准备阶段(2 分钟)**
```bash
# 0.1 确认当前状态
echo "=== 当前时间 ==="
date '+%Y-%m-%d %H:%M:%S'
echo ""
echo "=== 当前 Git 分支和 Commit ==="
git branch --show-current
git log --oneline -3
echo ""
echo "=== 检查是否有未提交的更改 ==="
git status --short
```
**预期输出示例**:
```
=== 当前时间 ===
2026-05-12 15:30:00
=== 当前 Git 分支和 Commit ===
main
abc1234 (HEAD -> main) feat: update hero animation
def5678 fix: improve mobile layout
ghi9012 chore: upgrade dependencies
=== 检查是否有未提交的更改 ===
M src/components/Hero.tsx
```
#### **Step 1:确认问题现象(2 分钟)**
```bash
# 1.1 检查网站是否可访问
curl -I https://novalon.cn/ | head -10
# 预期输出: HTTP/2 200
# 如果看到 500/502/503/504,说明需要紧急回滚
# 1.2 检查关键页面的 HTTP 状态码
for page in "/" "/about" "/contact" "/products" "/solutions"; do
status=$(curl -s -o /dev/null -w "%{http_code}" "https://novalon.cn${page}")
echo "$page -> $status"
done
# 预期输出: 所有页面都返回 200
# 1.3 检查关键 HTML 元素是否存在
curl -s https://novalon.cn/ | grep -E '<title>|<meta name="description">|<h1'
```
**预期输出示例**:
```
/ -> 200
/about -> 200
/contact -> 200
/products -> 200
/solutions -> 200
<title>四川睿新致远科技有限公司</title>
<meta name="description" content="..." />
<h1 class="...">...</h1>
```
如果上述检查有任何一项不通过,**立即进入 Step 2**。
#### **Step 2:定位稳定版本(3 分钟)**
```bash
# 2.1 查看 Git 历史,找到最近的稳定版本
git log --oneline --graph -20
# 寻找标记为 "stable"、"fix:"、"chore:" 的 commit
# 或者查看 Git Tags
git tag -l 'v*' --sort=-v:refname | head -5
# 如果没有 Tag,根据 commit message 判断
# 推荐选择最近一次包含以下关键词的 commit:
# - "fix:" (bug 修复)
# - "release:" 或 "v*.*.*" (正式发布)
# - "chore: bump version" (版本号更新)
```
**示例输出**:
```
* abc1234 (HEAD -> main) feat: update hero animation ← 当前版本(有问题)
* def5678 fix: improve mobile layout ← 可能是稳定版本
* ghi9012 chore: upgrade dependencies ← 上一个版本
* jkl3456 release: v1.0.0-stable ← 正式发布版(最安全)
```
**决策建议**
- 如果 `def5678` 是你上次验证过的版本,回滚到它
- 如果不确定,选择 `jkl3456` (Tagged release)
#### **Step 3:执行本地代码回滚(3 分钟)**
```bash
# 3.1 备份当前版本(以防万一)
git stash push -m "backup-before-rollback-$(date +%Y%m%d_%H%M%S)"
# 或者创建一个新的分支保存当前代码
git branch backup/broken-version-$(date +%Y%m%d)
# 3.2 切换到稳定版本
# 方法 A:使用 Git Tag(推荐)
git checkout v1.0.0-stable
# 方法 B:使用 Commit Hash
git checkout def5678
# 3.3 确认已切换成功
git log --oneline -1
# 应该显示: def5678 fix: improve mobile layout
echo "✅ 已切换到稳定版本"
```
#### **Step 4:重新构建并部署(5 分钟)**
```bash
# 4.1 清理并构建
npm run build:clean
# 如果构建成功,会看到类似输出:
# ✅ Built in Xs
# 📁 生成了 XXX 个文件,总大小: XX MB
# 4.2 快速验证构建产物
if [ -d "dist" ]; then
echo "✅ dist 目录存在"
# 检查关键文件是否存在
ls -lh dist/index.html
ls -lh dist/about/index.html
ls -lh dist/contact/index.html
# 检查 HTML 内容
head -20 dist/index.html | grep '<title>'
else
echo "❌ 构建失败!dist 目录不存在"
exit 1
fi
# 4.3 部署到生产环境
./deploy-dist.sh
# 脚本会自动执行:
# 1. 检查 dist 目录
# 2. 验证 SSH 连接
# 3. 备份旧版本(在服务器上)
# 4. 上传新的 dist
# 5. 设置权限
# 6. 重载 Nginx
# 7. 验证部署结果
```
#### **Step 5:验证回滚成功(2 分钟)**
```bash
# 5.1 等待 3-5 秒让 CDN 缓存刷新
sleep 5
# 5.2 再次执行 Step 1.2 和 1.3 的检查
for page in "/" "/about" "/contact" "/products"; do
status=$(curl -s -o /dev/null -w "%{http_code}" "https://novalon.cn${page}")
if [ "$status" = "200" ]; then
echo "$page -> $status"
else
echo "$page -> $status (需要进一步排查)"
fi
done
# 5.3 浏览器手动验证(重要!)
open https://novalon.cn/
# 手动检查清单:
# □ 首页正常加载,无白屏
# □ 导航栏可点击,所有链接正常工作
# □ Logo 显示正确(应该是书法字体)
# □ 主题切换按钮可用(如果有暗色模式)
# □ 移动端布局正常(可以用 Chrome DevTools 模拟)
# □ 表单可以打开(即使不提交)
```
#### **Step 6:通知相关人员(2 分钟)**
```bash
# 6.1 记录回滚操作日志
cat << EOF >> /tmp/rollback-log.txt
==========================================
回滚记录
==========================================
时间: $(date '+%Y-%m-%d %H:%M:%S')
操作人: $(whoami)
原因: [填写具体原因]
回滚前版本: abc1234 (feat: update hero animation)
回滚后版本: $(git log --oneline -1)
验证结果: ✅ 所有关键页面正常
耗时: 约 15 分钟
==========================================
EOF
# 6.2 发送通知(钉钉/企业微信/邮件)
# 示例:发送邮件给 dev-team@novalon.cn
cat << EOF | mail -s "⚠️ 已回滚 Novalon Website" dev-team@novalon.cn
Novalon Website 已完成紧急回滚
回滚时间: $(date '+%Y-%m-%d %H:%M:%S')
回滚原因: [填写具体原因,如"首页白屏"]
回滚前版本: abc1234 (feat: update hero animation)
回滚后版本: $(git describe --tags || git log --oneline -1)
验证状态: ✅ 所有关键页面已恢复正常访问
请相关开发者尽快排查问题根因。
回滚详情:
- 操作人: $(whoami)
- 服务器: 139.155.109.62
- 域名: https://novalon.cn
- 日志位置: /tmp/rollback-log.txt
技术支持联系人:
- 值班工程师: [填写姓名] - [填写电话]
- 技术负责人: [填写姓名] - [填写电话]
EOF
echo "✅ 回滚通知已发送"
```
---
## 🐳 **Type 2Docker 容器级回滚(当 Type 1 不可用时)**
### **适用场景**
- 本地代码库损坏或不可用
- 需要立即恢复,来不及重新构建
- 服务器上有自动备份
#### **步骤(全部在服务器上执行)**
```bash
# SSH 到生产服务器
ssh root@139.155.109.62
# Step 1: 查看当前容器状态
docker ps | grep novalon
# 预期输出:
# CONTAINER ID IMAGE STATUS NAMES
# xxxxxxxxxx novalon-website:latest Up 2 hours novalon-nginx-secure
# Step 2: 查看可用的备份
ls -lth /home/novalon/docker-app/novalon-static_backup_* | head -5
# 预期输出:
# drwxr-xr-x 20260512_153000 ← 最新备份(1 小时前)
# drwxr-xr-x 20260512_140000 ← 之前的备份(2 小时前)
# drwxr-xr-x 20260511_180000 ← 昨天的备份
# Step 3: 选择最近的备份进行恢复
BACKUP_DIR=$(ls -dt /home/novalon/docker-app/novalon-static_backup_* | head -1)
CURRENT_DIR="/home/novalon/docker-app/novalon-static"
echo "将回滚到备份: $BACKUP_DIR"
# Step 4: 执行回滚
rm -rf "$CURRENT_DIR"
cp -r "$BACKUP_DIR" "$CURRENT_DIR"
# Step 5: 重载 Nginx 使更改生效
docker exec novalon-nginx-secure nginx -s reload
# Step 6: 验证
curl -I https://novalon.cn/ | head -1
# 预期: HTTP/2 200
echo "✅ Docker 容器级回滚完成"
```
---
## 🌐 **Type 3CDN 缓存清理(配合 Type 1 或 Type 2 使用)**
### **何时需要?**
- 回滚后用户仍看到旧版本的缓存内容
- 更新了 CSS/JS 文件但浏览器未加载最新版本
#### **方法 A:强制刷新 Nginx 缓存(推荐)**
```bash
# 在服务器上执行
ssh root@139.155.109.62
# 临时禁用缓存(5 分钟后记得改回来)
cat > /tmp/disable-cache.conf << 'EOF'
location / {
add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate";
expires 0;
# ... 其他配置保持不变
}
EOF
# 应用配置并重载 Nginx
docker exec novalon-nginx-secure nginx -s reload
# 等待 5 分钟让所有用户的缓存过期
sleep 300
# 恢复正常缓存策略(重要!否则影响性能)
# 将原来的 nginx.conf 放回去
docker exec novalon-nginx-secure nginx -s reload
```
#### **方法 B:版本化静态资源(长期方案)**
如果你的项目使用了 `next.config.ts` 中的 `assetPrefix`,Next.js 会自动为静态资源添加 hash:
```
旧版本: /_next/static/css/abc123.css
新版本: /_next/static/css/def456.css
```
这样浏览器会自动请求新的 URL,无需手动清除缓存。
---
## 📞 **紧急联系人列表**
| 角色 | 姓名 | 电话/微信 | 职责 | 备注 |
|------|------|-----------|------|------|
| **值班工程师** | 待填写 | 待填写 | 执行回滚操作 | 第一响应人 |
| **技术负责人** | 待填写 | 待填写 | 决策是否回滚 | P0/P1 故障需其批准 |
| **产品负责人** | 待填写 | 待填写 | 评估业务影响 | P1/P2 故障需通知 |
| **运维支持** | 待填写 | 待填写 | 服务器/DNS 层面支持 | 当涉及基础设施问题时 |
| **Sentry 告警接收人** | dev-team@novalon.cn | - | 错误监控告警 | Sentry 配置 |
---
## 📊 **回滚后复盘模板(必填!)**
每次回滚完成后,**必须在 24 小时内**填写此模板并发送到团队群:
```markdown
## Novalon Website 回滚复盘报告
**基本信息**
- 回滚日期和时间:
- 发现问题时间:
- 开始回滚时间:
- 回滚完成时间:
- 总宕机时间: ___ 分钟
**问题分类**
- [ ] 代码 Bug(哪个 commit 引入的?commit hash: _____
- [ ] 依赖兼容性问题(哪个包升级导致?包名及版本: _____
- [ ] 配置错误(nginx/docker/env?具体是哪个配置?)
- [ ] 第三方服务故障(CDN/DNS/SSL 证书?服务商是谁?)
- [ ] 其他: _____
**问题根因分析**
(详细描述为什么会出现这个问题)
**影响范围评估**
- 影响用户数估算: 约 ___ 人
- 受影响的页面/功能:
- 是否造成数据丢失: 是/否(如果是,哪些数据?)
- 业务损失估算:
**回滚操作详情**
- 回滚类型: Type 1 (代码回滚) / Type 2 (Docker 容器级) / Type 3 (CDN 清理)
- 回滚前版本:
- 回滚后版本:
- 是否成功恢复: 是/否
- 是否需要后续修复: 是/否
**改进措施(防止再次发生)**
1.
2.
3.
**如何改进测试/CI 流程以提前发现问题**
- [ ] 补充单元测试覆盖(具体是哪个模块?)
- [ ] 增加 E2E 测试用例(具体场景是什么?)
- [ ] 在 CI Pipeline 中增加质量门禁(什么条件?)
- [ ] 接入 Sentry 错误监控(已完成 ✓)
- [ ] 完善 Code Review 流程(什么标准?)
- [ ] 其他:
**经验教训总结**
(用一两句话总结这次回滚学到了什么)
**附件**
- 截图/日志: (如有)
- 相关 Issue/PR 链接: (如有)
```
---
## 🔧 **常见问题排查(FAQ**
### **Q1:回滚后网站仍然显示旧内容?**
**ACDN 缓存未刷新。解决方案:**
1. 执行 Type 3: CDN 缓存清理
2. 或等待 CDN TTL 过期(通常 1-2 小时)
3. 或使用 Ctrl+Shift+R 强制刷新浏览器缓存
### **Q2Git checkout 失败,提示"有未提交的更改"**
**A:先暂存或丢弃这些更改:**
```bash
# 查看有哪些未提交的更改
git status
# 方案 A:暂时保存(推荐)
git stash push -m "temp-save"
# 方案 B:直接丢弃(谨慎!不可逆)
git reset --hard HEAD
# 然后再执行 git checkout
```
### **Q3npm run build:clean 构建失败?**
**A:可能的原因及解决方法:**
1. **依赖未安装完全**:运行 `rm -rf node_modules && npm install`
2. **TypeScript 类型错误**:运行 `npx tsc --noEmit` 查看详细错误
3. **ESLint 错误**:运行 `npm run lint` 查看详情
4. **内存不足**:增加 Node.js 内存限制 `NODE_OPTIONS=--max-old-space-size=4096 npm run build:clean`
### **Q4SSH 连接到服务器失败?**
**A:检查以下几点:**
1. **网络连接**`ping 139.155.109.62`
2. **SSH 服务**`ssh -v root@139.155.109.62`(查看详细日志)
3. **防火墙**:确认端口 22 未被封锁
4. **SSH Key**:确认私钥文件权限正确 (`chmod 600 ~/.ssh/id_rsa`)
### **Q5:回滚后发现数据库或其他动态内容丢失?**
**A:对于纯静态网站(你的情况),不存在这个问题!**
- Novalon Website 是纯静态导出,不依赖数据库
- 所有内容都在 `dist/` 目录中
- 回滚只是替换静态文件,不会影响任何持久化数据
---
## ⚡ **快速参考卡片(打印出来贴在工位上)**
```
╔══════════════════════════════════════════╗
║ Novalon Website 紧急回滚速查表 ║
╠══════════════════════════════════════════╣
║ ║
║ P0 触发条件: ║
║ • 首页白屏 / 5xx 错误 ║
║ • 安全漏洞 ║
║ • 域名/SSL 问题 ║
║ ║
║ 快速回滚命令(3 步完成): ║
║ ║
║ 1. git log --oneline -10 ║
║ # 找到稳定版本的 commit ║
║ ║
║ 2. git checkout <stable-commit-hash> ║
║ # 切换到稳定版本 ║
║ ║
║ 3. ./deploy-dist.sh ║
║ # 重新构建并部署 ║
║ ║
║ 验证命令: ║
║ curl -I https://novalon.cn/ ║
║ # 预期: HTTP/2 200 ║
║ ║
║ 紧急联系人: ║
║ • 值班工程师: [姓名] - [电话] ║
║ • 技术负责人: [姓名] - [电话] ║
║ • 运维支持: [姓名] - [电话] ║
║ ║
║ 服务器信息: ║
║ IP: 139.155.109.62 ║
║ 用户: root ║
║ 域名: novalon.cn ║
║ 容器: novalon-nginx-secure ║
║ ║
║ 目标恢复时间: < 10 分钟 ║
╚══════════════════════════════════════════╝
```
---
## ✅ **回滚完成清单**
请在回滚完成后逐项确认:
**立即确认(回滚后 5 分钟内)**
- [ ] 网站首页可访问,无白屏
- [ ] HTTP 状态码返回 200
- [ ] 关键页面(About, Contact, Products)可访问
- [ ] 导航栏正常工作
- [ ] SEO 元数据完整(title, description, OG tags
- [ ] 已通知相关人员(邮件/群消息)
**后续确认(回滚后 24 小时内)**
- [ ] 填写回滚复盘报告
- [ ] 分析问题根因并记录
- [ ] 制定预防措施
- [ ] 更新 CI/CD Pipeline(如有必要)
- [ ] 团队内部分享经验教训
---
## 📚 **相关文档链接**
- **部署脚本**: [deploy-dist.sh](./deploy-dist.sh)
- **Jenkins Pipeline**: [Jenkinsfile](./Jenkinsfile)
- **Sentry 监控指南**: [docs/sentry-setup-guide.md](./docs/sentry-setup-guide.md)
- **技术栈降级指南**: [scripts/downgrade-stack.sh](./scripts/downgrade-stack.sh)
- **CONTEXT.md**: [CONTEXT.md](./CONTEXT.md)(领域术语和关键决策)
---
**💡 最后提醒**
- 保持冷静,按照步骤执行
- 每一步都要验证再继续
- 记录所有操作,方便事后复盘
- 回滚不是失败,是负责任的表现!
**祝你好运!🍀**