# 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 元数据丢失:
- `
` 为空或显示 "Untitled"
- `` 缺失
- 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 '|| 200
/about -> 200
/contact -> 200
/products -> 200
/solutions -> 200
四川睿新致远科技有限公司
...
```
如果上述检查有任何一项不通过,**立即进入 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 ''
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 2:Docker 容器级回滚(当 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 3:CDN 缓存清理(配合 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:回滚后网站仍然显示旧内容?**
**A:CDN 缓存未刷新。解决方案:**
1. 执行 Type 3: CDN 缓存清理
2. 或等待 CDN TTL 过期(通常 1-2 小时)
3. 或使用 Ctrl+Shift+R 强制刷新浏览器缓存
### **Q2:Git checkout 失败,提示"有未提交的更改"?**
**A:先暂存或丢弃这些更改:**
```bash
# 查看有哪些未提交的更改
git status
# 方案 A:暂时保存(推荐)
git stash push -m "temp-save"
# 方案 B:直接丢弃(谨慎!不可逆)
git reset --hard HEAD
# 然后再执行 git checkout
```
### **Q3:npm 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`
### **Q4:SSH 连接到服务器失败?**
**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 ║
║ # 切换到稳定版本 ║
║ ║
║ 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)(领域术语和关键决策)
---
**💡 最后提醒**:
- 保持冷静,按照步骤执行
- 每一步都要验证再继续
- 记录所有操作,方便事后复盘
- 回滚不是失败,是负责任的表现!
**祝你好运!🍀**