<!-- title: Claude Code大规模重构与架构迁移实战 -->

# Claude Code大规模重构与架构迁移实战

## 概述

本教程面向有6个月以上Claude Code使用经验的中高级开发者，聚焦如何利用Claude Code的上下文工程、多文件编辑、Workflow编排等核心能力，安全高效地完成大规模代码重构和架构迁移任务。学完本教程，你将掌握从重构规划、增量迁移到质量守卫的完整方法论，能够在真实项目中用Claude Code完成万行级代码的架构升级。

## 前置条件

- Claude Code CLI已安装并完成基础配置（`claude` 命令可用）
- 熟悉Git基本操作（分支、合并、冲突解决）
- 有一个可实践的代码仓库（建议使用真实的中小型项目）
- 了解基本的软件架构概念（分层、依赖注入、设计模式）

---

## 一、大规模重构的核心挑战与Claude Code的解法

### 1.1 为什么传统重构方式效率低下

大规模重构面临三个核心痛点：

| 痛点 | 具体表现 | 传统解法成本 |
|------|----------|-------------|
| **影响范围不可控** | 一个接口改动影响50+个文件，手动排查遗漏率高 | 需要全局搜索+人工判断 |
| **上下文窗口有限** | 人脑无法同时持有数千行代码的完整认知 | 反复跳转文件，效率断崖式下降 |
| **回归风险高** | 重构引入隐蔽bug，测试覆盖不足时难以发现 | 需要大量手工测试 |

Claude Code的独特优势在于：它能同时持有数千行代码的上下文，理解跨文件的语义依赖关系，并通过Workflow编排实现"理解→规划→执行→验证"的闭环。

### 1.2 重构决策矩阵

在开始前，用以下矩阵判断你的重构是否适合交给Claude Code：

```
重构适合度评分 = (文件变更数 × 2) + (模式一致性 × 3) + (测试覆盖率 × 2) - (业务逻辑复杂度 × 2)

- 文件变更数 > 20：+高分（批量操作是Claude Code强项）
- 模式一致性高（同样的改动模式重复出现）：+高分
- 测试覆盖率 > 60%：+高分（有安全网）
- 业务逻辑复杂（需要深度领域知识）：-高分（需人工参与决策）
```

**适合Claude Code的重构场景**：
- 框架升级（React 18→19、Next.js 13→15）
- API版本迁移（REST→GraphQL、v1→v2）
- 设计模式统一（统一错误处理、统一日志格式）
- 语言特性迁移（JavaScript→TypeScript、Class→Hooks）
- 依赖清理与替换

**不适合纯Claude Code的场景**：
- 需要与产品经理确认的业务逻辑变更
- 涉及数据库Schema的重大变更（需DBA审核）
- 安全敏感的认证授权流程重构

---

## 二、重构前的情报收集——用Claude Code绘制代码地图

### 2.1 启动情报收集会话

重构的第一步不是写代码，而是理解现状。用Claude Code的非交互模式快速扫描项目：

```bash
# 第一步：生成项目结构概览
claude -p "分析当前项目的目录结构和架构模式，输出：
1. 主要模块及其职责
2. 模块间的依赖关系（用列表表示）
3. 识别出可能的循环依赖
4. 外部依赖清单（package.json或requirements.txt中的关键依赖）

格式要求：每个模块用3-5句话描述，依赖关系用A→B的格式" \
  --allowedTools "Read,Glob,Grep" > project-analysis.md
```

**预期输出**（示例）：

```
## 项目结构分析

### 模块清单
1. `src/api/` - REST API层，包含用户、订单、商品三个子模块
   - 职责：HTTP请求处理、参数验证、响应序列化
   - 问题：部分业务逻辑泄露到Controller中

2. `src/services/` - 业务逻辑层
   - 职责：核心业务规则、数据编排
   - 问题：与API层存在双向依赖

### 依赖关系
src/api → src/services → src/repositories → src/models
src/api → src/utils（循环：src/utils → src/api）

### 循环依赖警告
- src/utils/httpClient.ts 导入了 src/api/interceptors.ts
- 建议将 interceptors 提取为独立模块
```

### 2.2 精确定位变更影响范围

假设我们要将项目从Express迁移到Fastify，首先确定影响范围：

```bash
# 搜索所有Express特有的API调用
claude -p "搜索整个项目中所有使用Express特有API的位置，包括但不限于：
- express() 应用创建
- req/res 对象的Express特有方法
- express.Router()
- express中间件（bodyParser, cors等）
- 错误处理中间件 (err, req, res, next) 四参数模式

输出格式：文件路径:行号 | 具体代码 | Express API | Fastify等价写法建议" \
  --allowedTools "Grep,Read,Glob"
```

### 2.3 生成依赖热力图

利用Claude Code的Grep能力统计每个文件的被引用次数：

```bash
# 找出被最多文件引用的模块（高风险变更点）
claude -p "统计src/目录下所有TypeScript/JavaScript文件的被导入次数。
对每个文件，计算有多少其他文件导入了它。
按被导入次数降序排列，输出前30个文件。
标注被导入超过10次的文件为[HIGH RISK]。" \
  --allowedTools "Grep,Read,Glob"
```

### 2.4 建立重构基线

在动手之前，确保有安全网：

```bash
# 1. 创建重构专用分支
git checkout -b refactor/express-to-fastify

# 2. 确保测试通过
claude -p "运行项目的完整测试套件，记录当前测试结果。
如果有失败的测试，分析原因并输出修复建议。
最终输出：总测试数、通过数、失败数、跳过数" \
  --allowedTools "Bash"

# 3. 创建CLAUDE.md记录重构计划
# 在项目根目录的CLAUDE.md中添加重构上下文
```

在项目的 `CLAUDE.md` 中记录重构元信息：

```markdown
## 当前重构任务

### 目标
将Web框架从Express 4.x迁移到Fastify 5.x

### 约束
- 保持所有现有API端点的行为不变
- 必须通过所有现有测试
- 增量迁移，每个PR不超过500行变更
- 中间件迁移优先级：认证 > 日志 > 错误处理 > 其他

### 进度追踪
- [ ] Phase 1: 基础设施层（应用创建、配置加载）
- [ ] Phase 2: 中间件迁移（按优先级顺序）
- [ ] Phase 3: 路由注册方式迁移
- [ ] Phase 4: 请求/响应处理方式适配
- [ ] Phase 5: 错误处理统一
- [ ] Phase 6: 测试适配与验证

### 风险点
- Express的(req, res, next)签名需改为Fastify的(request, reply)签名
- 第三方中间件可能没有Fastify等价物
- 文件上传处理方式完全不同
```

---

## 三、规划阶段——用EnterPlanMode制定迁移策略

### 3.1 进入计划模式

Claude Code的Plan Mode是大规模重构的利器。当你给它一个复杂的重构任务时，它不会直接开始改代码，而是先输出完整的执行计划供你审核：

```
> 我需要将这个Express项目迁移到Fastify。请先制定详细的迁移计划，
> 覆盖所有src/目录下的文件。要求：
> 1. 按模块分批次，每批变更不超过10个文件
> 2. 每批变更后测试应全部通过
> 3. 标注每批变更的风险等级（低/中/高）
```

Claude Code会进入Plan Mode，读取项目文件，分析依赖关系，然后输出类似这样的计划：

```
## 迁移计划：Express → Fastify

### Phase 1: 基础设施 [风险：低]
变更文件：3个
- src/app.ts: 替换express()为fastify()
- src/server.ts: 更新启动逻辑
- src/config/index.ts: 添加Fastify配置项

### Phase 2: 错误处理中间件 [风险：中]
变更文件：5个
- src/middleware/errorHandler.ts: 重写为Fastify插件
- src/middleware/notFound.ts: 迁移到Fastify 404处理
- src/api/users/index.ts: 错误处理适配
- src/api/orders/index.ts: 错误处理适配
- src/api/products/index.ts: 错误处理适配

### Phase 3-6: [后续阶段...]

### 执行顺序依赖图
Phase 1 → Phase 2 → Phase 3（依赖Phase 1的应用实例）
                    → Phase 4（可与Phase 3并行）
         Phase 5 → Phase 6（最终验证）
```

### 3.2 审核与调整计划

计划输出后，你可以：

```bash
# 调整计划的执行顺序
> 将Phase 3和Phase 4的执行顺序对调，因为路由注册更关键

# 给特定阶段增加约束
> Phase 2中，errorHandler需要同时支持新旧格式，方便回滚

# 拆分过大的阶段
> Phase 3涉及的文件太多，按api子模块拆成3a/3b/3c三个子阶段
```

### 3.3 工作流程图

以下是完整的重构工作流程：

```mermaid
flowchart TD
    A[启动重构任务] --> B[情报收集阶段]
    B --> B1[项目结构分析]
    B --> B2[依赖热力图]
    B --> B3[变更影响范围]
    B --> B4[测试基线建立]

    B1 & B2 & B3 & B4 --> C[规划阶段<br/>EnterPlanMode]
    C --> C1[生成分批迁移计划]
    C --> C2[人工审核调整]
    C --> C3[记录到CLAUDE.md]

    C1 & C2 & C3 --> D[执行阶段]
    D --> D1[Phase N: 批量文件修改]
    D1 --> D2[运行测试验证]
    D2 --> D3{测试通过?}
    D3 -->|是| D4[Git提交]
    D3 -->|否| D5[Claude Code自动修复]
    D5 --> D2
    D4 --> D6{还有更多Phase?}
    D6 -->|是| D1
    D6 -->|否| E[最终验证阶段]

    E --> E1[全量测试]
    E --> E2[性能基准对比]
    E --> E3[代码审查]
    E1 & E2 & E3 --> F[合并到主分支]

    style B fill:#e1f5fe
    style C fill:#fff3e0
    style D fill:#e8f5e9
    style E fill:#fce4ec
    style F fill:#f3e5f5
```

---

## 四、执行阶段——增量迁移的六步法

### 4.1 Step 1: 创建适配层（Bridge Pattern）

大规模迁移的核心策略是**适配层模式**：先建桥，再迁移，最后拆桥。

```bash
# 让Claude Code创建适配层
> 请在src/adapters/目录下创建一个ExpressToFastify适配层，包含：
> 1. expressToFastifyMiddleware.ts - 将Express中间件包装为Fastify插件
> 2. expressToFastifyHandler.ts - 将(req,res,next)处理器转换为(request,reply)
> 3. expressToFastifyRouter.ts - 将Express Router映射为Fastify路由
> 
> 这些适配器应该：
> - 保持原有函数签名不变
> - 内部使用Fastify API
> - 添加@deprecated JSDoc注释
> - 包含完整的TypeScript类型定义
```

**生成的适配器示例**（`src/adapters/expressToFastifyHandler.ts`）：

```typescript
import { FastifyRequest, FastifyReply } from 'fastify';
import { Request, Response, NextFunction } from 'express';

type ExpressHandler = (
  req: Request,
  res: Response,
  next: NextFunction
) => void | Promise<void>;

/**
 * @deprecated 仅用于Express→Fastify迁移过渡期
 * 将Express风格的请求处理器适配为Fastify风格
 */
export function adaptHandler(handler: ExpressHandler) {
  return async (request: FastifyRequest, reply: FastifyReply) => {
    // 映射Express req → Fastify request
    const expressReq = mapToExpressRequest(request);
    const expressRes = mapToExpressResponse(reply);
    
    try {
      await handler(expressReq, expressRes, () => {});
    } catch (error) {
      reply.status(500).send({ error: 'Internal Server Error' });
    }
  };
}
```

### 4.2 Step 2: 逐模块迁移——利用TaskList追踪进度

使用Claude Code的任务列表功能追踪迁移进度：

```
> 请创建以下任务列表来追踪Fastify迁移进度：
> 
> 1. [ ] 迁移 src/app.ts - 替换框架创建逻辑
> 2. [ ] 迁移 src/middleware/auth.ts - JWT认证中间件
> 3. [ ] 迁移 src/middleware/logger.ts - 请求日志中间件  
> 4. [ ] 迁移 src/api/users/ - 用户模块路由
> 5. [ ] 迁移 src/api/orders/ - 订单模块路由
> 6. [ ] 迁移 src/api/products/ - 商品模块路由
> 7. [ ] 迁移 src/middleware/errorHandler.ts - 全局错误处理
> 8. [ ] 更新所有测试文件
> 9. [ ] 删除适配层
> 10. [ ] 最终全量验证
> 
> 任务依赖关系：1→2,3; 2,3→4,5,6; 4,5,6→7; 7→8; 8→9; 9→10
```

### 4.3 Step 3: 执行单模块迁移

对每个模块，使用Claude Code的Plan Mode确保安全：

```
> 现在开始执行任务1：迁移 src/app.ts
> 
> 要求：
> 1. 先读取当前文件内容
> 2. 识别所有Express特有API
> 3. 用Fastify等价API替换
> 4. 保持所有导出接口不变
> 5. 运行测试验证
```

Claude Code的典型执行流程：

```
[读取] src/app.ts（45行）
[分析] 识别到3个Express特有调用：
  - Line 5: const app = express()
  - Line 12: app.use(express.json())
  - Line 25: app.listen(port, callback)

[修改] 执行替换：
  - express() → fastify({ logger: true })
  - app.use(express.json()) → 已内置，删除
  - app.listen() → app.listen({ port, host })

[验证] 运行 npm test
  ✓ 23 tests passed
  ✓ 0 tests failed

[标记] 任务1完成 ✓
```

### 4.4 Step 4: 批量模式迁移——利用Workflow编排

当模式一致时（如所有Controller都需要同样的签名变更），使用Workflow进行批量处理：

```
> 所有API路由文件都有相同的签名变更需求：
> 将 (req: Request, res: Response, next: NextFunction) 
> 改为 (request: FastifyRequest, reply: FastifyReply)
> 
> 请用批量方式处理 src/api/ 下的所有路由文件。
> 每个文件处理完后运行该模块的测试。
> 如果测试失败，自动回滚该文件的修改并报告问题。
```

Workflow编排自动执行：

```mermaid
flowchart LR
    subgraph "并行处理模块"
        M1[users路由<br/>3个文件] --> T1[运行users测试]
        M2[orders路由<br/>4个文件] --> T2[运行orders测试]
        M3[products路由<br/>2个文件] --> T3[运行products测试]
    end

    T1 --> R1{通过?}
    T2 --> R2{通过?}
    T3 --> R3{通过?}

    R1 -->|是| C1[提交 ✓]
    R1 -->|否| F1[回滚并报告]
    R2 -->|是| C2[提交 ✓]
    R2 -->|否| F2[回滚并报告]
    R3 -->|是| C3[提交 ✓]
    R3 -->|否| F3[回滚并报告]

    C1 & C2 & C3 --> S[汇总结果]
    F1 & F2 & F3 --> S
```

### 4.5 Step 5: 处理棘手的迁移场景

**场景A：第三方中间件没有Fastify等价物**

```
> 我发现项目使用了express-fileupload中间件，Fastify没有直接等价物。
> 请研究：
> 1. Fastify生态中最接近的替代品是什么
> 2. 提供两种方案：a) 使用Fastify原生multipart b) 通过适配层包装原中间件
> 3. 列出每种方案的pros/cons
> 4. 推荐一种方案并给出实现代码
```

**场景B：渐进式共存——Express和Fastify同时运行**

在某些大型项目中，不可能一次性切换框架。使用代理模式实现共存：

```typescript
// src/adapters/dualFramework.ts
// Express和Fastify共存的桥接层

import express from 'express';
import fastify from 'fastify';

export class DualFrameworkApp {
  private expressApp = express();
  private fastifyApp = fastify();
  
  // 已迁移的路由走Fastify
  private migratedRoutes = new Set<string>();
  
  async handleRequest(req: any, res: any) {
    const routeKey = `${req.method}:${req.route?.path}`;
    
    if (this.migratedRoutes.has(routeKey)) {
      // 转发给Fastify处理
      await this.fastifyApp.inject({
        method: req.method,
        url: req.url,
        payload: req.body,
      });
    } else {
      // 仍由Express处理
      this.expressApp(req, res);
    }
  }
  
  markMigrated(method: string, path: string) {
    this.migratedRoutes.add(`${method}:${path}`);
  }
}
```

### 4.6 Step 6: 验证与收尾

```bash
# 全面验证
claude -p "执行最终验证：
1. 运行完整测试套件，确保100%通过
2. 搜索整个项目，确认没有残留的express导入
3. 检查所有TypeScript类型是否正确
4. 对比迁移前后的API响应格式，确认兼容
5. 输出最终的变更统计：文件数、行数、删除/新增

如有任何问题，输出详细的问题报告和修复建议。" \
  --allowedTools "Bash,Grep,Read,Glob"
```

---

## 五、高级技巧——让Claude Code成为重构利器

### 5.1 利用记忆系统维护重构上下文

跨会话的大型重构中，Claude Code的记忆系统（Memory）是防止上下文丢失的关键：

```
> 请记住以下重构上下文到你的记忆文件中：
> 
> 项目：ecommerce-api
> 当前重构：Express → Fastify迁移
> 已完成阶段：Phase 1-3
> 当前阶段：Phase 4（路由适配）
> 剩余工作：Phase 5-6
> 
> 关键决策记录：
> - 决定使用@fastify/multipart替代express-fileupload
> - 错误处理采用Fastify的setErrorHandler而非中间件
> - 暂时保留适配层，Phase 6统一删除
> 
> 已知问题：
> - orders模块的文件上传功能需要在Phase 5特殊处理
> - tests/fixtures/中的mock对象仍使用Express类型
```

这样在下次会话中，Claude Code会自动加载这些上下文：

```bash
# 新会话中继续重构
claude

> 继续Fastify迁移，从上次停下的Phase 4开始
# Claude Code会从记忆中恢复上下文，无缝继续
```

### 5.2 使用CLAUDE.md建立项目级重构规则

在项目的 `.claude/` 目录下创建 `CLAUDE.md`，为Claude Code提供持久化的重构指导：

```markdown
# 项目重构指南

## 架构约束
- Web框架：Fastify 5.x（迁移中，部分模块仍用Express）
- 禁止新增Express依赖
- 新代码必须使用Fastify API
- 所有新中间件必须是Fastify插件格式

## 迁移编码规范
- 路由处理器签名：(request: FastifyRequest, reply: FastifyReply) => Promise<void>
- 错误抛出：使用 reply.status(code).send({error}) 而非 throw
- 请求体访问：request.body（不是req.body）
- 查询参数：request.query（不是req.query）
- 路径参数：request.params（不是req.params）

## 测试要求
- 每个迁移的模块必须有对应的集成测试
- 测试使用 supertest 或 Fastify的 inject() 方法
- 迁移前后的测试用例必须保持一致

## 文件命名
- 适配器文件放在 src/adapters/
- 已迁移的文件顶部添加注释：// Migrated to Fastify
```

### 5.3 用Hooks自动化重构质量检查

在 `.claude/settings.json` 中配置Hooks，在每次代码修改后自动运行质量检查：

```json
{
  "hooks": {
    "afterEdit": [
      {
        "matcher": "src/**/*.ts",
        "command": "npx tsc --noEmit --pretty 2>&1 | head -20",
        "description": "TypeScript类型检查"
      }
    ],
    "afterWrite": [
      {
        "matcher": "src/**/*.ts",
        "command": "npx eslint ${FILE} --max-warnings=0 2>&1 | tail -5",
        "description": "ESLint检查修改的文件"
      }
    ]
  }
}
```

### 5.4 上下文窗口管理策略

大规模重构时，上下文窗口是最宝贵的资源。以下是优化策略：

**策略一：分而治之**

```bash
# 不要一次性处理整个项目，按模块分解
# 错误示范：
claude -p "把整个项目从Express迁移到Fastify"  # 上下文会爆

# 正确做法：
claude -p "只迁移 src/middleware/auth.ts 到 Fastify，不要修改其他文件"
```

**策略二：利用Grep减少读取量**

```bash
# 让Claude Code用Grep定位而非读取整个文件
claude -p "找到所有使用了express.Router()的文件，
列出文件路径和行号即可，不要读取文件内容" \
  --allowedTools "Grep,Glob"
```

**策略三：会话间状态传递**

```bash
# 会话1：完成分析，保存结果
claude -p "分析迁移影响范围，将结果保存到 refactor-plan.md" \
  --allowedTools "Read,Grep,Glob,Write"

# 会话2：读取分析结果，开始执行
claude -p "读取 refactor-plan.md，按照Phase 1的计划执行迁移" \
  --allowedTools "Read,Grep,Glob,Edit,Bash"
```

### 5.5 非交互模式批量执行

对于确定性的、模式一致的迁移任务，使用 `-p` 模式配合脚本实现自动化：

```bash
#!/bin/bash
# batch-migrate.sh - 批量迁移脚本

MODULES=("users" "orders" "products" "inventory" "payments")

for module in "${MODULES[@]}"; do
  echo "=== 迁移模块: $module ==="
  
  claude -p "迁移 src/api/$module/ 目录下所有路由到Fastify格式。
  要求：
  1. 将(req, res, next)改为(request, reply)
  2. 将res.json()改为reply.send()
  3. 将res.status().json()改为reply.status().send()
  4. 将next(error)改为reply.send(error)
  5. 运行 npm test -- --grep '$module' 验证
  
  如果测试失败，输出失败原因并停止。" \
    --allowedTools "Read,Edit,Grep,Glob,Bash"
  
  if [ $? -ne 0 ]; then
    echo "❌ 模块 $module 迁移失败，停止批量执行"
    exit 1
  fi
  
  echo "✅ 模块 $module 迁移完成"
  
  # 自动提交
  git add src/api/$module/
  git commit -m "refactor: migrate $module routes from Express to Fastify"
done

echo "🎉 所有模块迁移完成"
```

---

## 六、实战案例——Next.js Pages Router到App Router迁移

让我们用一个完整的案例来演示上述方法论。这是一个真实的迁移场景：将Next.js 13的Pages Router迁移到App Router。

### 6.1 情报收集

```bash
claude -p "分析这个Next.js项目的路由结构：
1. 列出pages/目录下所有路由文件
2. 识别使用了getServerSideProps的页面
3. 识别使用了getStaticProps/getStaticPaths的页面
4. 识别使用了API Routes的端点
5. 统计每个页面使用的Next.js特有API

按迁移复杂度（简单→复杂）排序输出" \
  --allowedTools "Read,Grep,Glob"
```

**预期输出**：

```
## 路由迁移分析

### 简单（纯静态页面，无数据获取）
- pages/about.tsx - 纯展示页面
- pages/contact.tsx - 纯表单页面
- pages/404.tsx - 自定义404

### 中等（使用getServerSideProps）
- pages/index.tsx - 首页，获取文章列表
- pages/blog/[slug].tsx - 博客详情页
- pages/dashboard.tsx - 用户仪表盘

### 复杂（API Routes + 混合数据获取）
- pages/api/auth/[...nextauth].ts - NextAuth API
- pages/api/webhooks.ts - Webhook处理
- pages/api/graphql.ts - GraphQL端点

### 统计
- getServerSideProps: 3个页面
- getStaticProps: 1个页面
- API Routes: 3个端点
- 使用useRouter: 5个组件
```

### 6.2 生成迁移计划

```
> 基于上面的分析，制定App Router迁移计划。
> 
> 约束：
> - Pages Router和App Router必须能共存（Next.js支持）
> - 优先迁移简单页面验证流程
> - API Routes最后迁移（影响最大）
> - 每个页面迁移后验证功能完整性
```

### 6.3 执行迁移——以博客详情页为例

```
> 迁移 pages/blog/[slug].tsx 到 app/blog/[slug]/page.tsx
> 
> 当前页面使用了：
> - getServerSideProps 获取博客内容
> - remark/remark-html 渲染Markdown
> - useSession 检查登录状态
> 
> 迁移要求：
> 1. getServerSideProps → Server Component直接fetch
> 2. 保持URL结构不变：/blog/[slug]
> 3. 客户端交互部分提取为Client Component
> 4. 添加loading.tsx和error.tsx
> 5. SEO元数据使用generateMetadata
```

**Claude Code生成的迁移代码**：

```typescript
// app/blog/[slug]/page.tsx
import { notFound } from 'next/navigation';
import { Metadata } from 'next';
import { BlogContent } from './blog-content';
import { getPost, getPostSlugs } from '@/lib/blog';

// SEO元数据生成
export async function generateMetadata({
  params,
}: {
  params: { slug: string };
}): Promise<Metadata> {
  const post = await getPost(params.slug);
  if (!post) return { title: 'Post Not Found' };
  
  return {
    title: post.title,
    description: post.excerpt,
    openGraph: {
      title: post.title,
      description: post.excerpt,
      type: 'article',
    },
  };
}

// 静态参数生成（替代getStaticPaths）
export async function generateStaticParams() {
  const slugs = await getPostSlugs();
  return slugs.map((slug) => ({ slug }));
}

// Server Component - 替代getServerSideProps
export default async function BlogPostPage({
  params,
}: {
  params: { slug: string };
}) {
  const post = await getPost(params.slug);
  
  if (!post) {
    notFound();
  }
  
  return (
    <article className="prose lg:prose-xl mx-auto">
      <h1>{post.title}</h1>
      <time dateTime={post.date}>{post.formattedDate}</time>
      {/* 客户端交互组件 */}
      <BlogContent 
        content={post.htmlContent} 
        slug={params.slug}
      />
    </article>
  );
}
```

```typescript
// app/blog/[slug]/blog-content.tsx
'use client';

import { useState } from 'react';
import { useSession } from 'next-auth/react';
import { ShareButton } from './share-button';

export function BlogContent({ 
  content, 
  slug 
}: { 
  content: string; 
  slug: string; 
}) {
  const { data: session } = useSession();
  const [liked, setLiked] = useState(false);
  
  return (
    <>
      <div dangerouslySetInnerHTML={{ __html: content }} />
      
      {session && (
        <div className="flex gap-4 mt-8">
          <button onClick={() => setLiked(!liked)}>
            {liked ? '❤️' : '🤍'} Like
          </button>
          <ShareButton slug={slug} />
        </div>
      )}
    </>
  );
}
```

```typescript
// app/blog/[slug]/loading.tsx
export default function BlogPostLoading() {
  return (
    <div className="animate-pulse">
      <div className="h-8 bg-gray-200 rounded w-3/4 mb-4" />
      <div className="h-4 bg-gray-200 rounded w-1/4 mb-8" />
      <div className="space-y-3">
        {Array.from({ length: 10 }).map((_, i) => (
          <div key={i} className="h-4 bg-gray-200 rounded" />
        ))}
      </div>
    </div>
  );
}
```

### 6.4 验证迁移结果

```bash
claude -p "验证 app/blog/[slug]/ 的迁移结果：
1. 对比 pages/blog/[slug].tsx 和 app/blog/[slug]/page.tsx 的功能列表
2. 确认所有原有功能都已覆盖
3. 运行 npm run build 确认无构建错误
4. 检查TypeScript类型是否正确
5. 输出功能对比清单" \
  --allowedTools "Read,Bash,Grep"
```

### 6.5 完整迁移架构图

```text
flowchart TB
    subgraph "迁移前 - Pages Router"
        P1[pages/index.tsx<br/>getServerSideProps]
        P2[pages/blog/_slug_.tsx<br/>getStaticProps]
        P3[pages/about.tsx<br/>静态页面]
        P4[pages/api/auth/[...nextauth].ts<br/>API Route]
        P5[pages/api/webhooks.ts<br/>API Route]
    end

    subgraph "迁移后 - App Router"
        A1["app/page.tsx<br/>Server Component"]
        A2["app/blog/_slug_/page.tsx<br/>Server Component + generateStaticParams"]
        A3["app/about/page.tsx<br/>Server Component"]
        A4["app/api/auth/[...nextauth]/route.ts<br/>Route Handler"]
        A5["app/api/webhooks/route.ts<br/>Route Handler"]

        A2_L[loading.tsx]
        A2_E[error.tsx]
        A2_C[blog-content.tsx<br/>Client Component]
    end

    P1 -.->|迁移| A1
    P2 -.->|迁移| A2
    P3 -.->|迁移| A3
    P4 -.->|迁移| A4
    P5 -.->|迁移| A5

    style P1 fill:#ffcdd2
    style P2 fill:#ffcdd2
    style P3 fill:#ffcdd2
    style P4 fill:#ffcdd2
    style P5 fill:#ffcdd2
    style A1 fill:#c8e6c9
    style A2 fill:#c8e6c9
    style A3 fill:#c8e6c9
    style A4 fill:#c8e6c9
    style A5 fill:#c8e6c9
```

---

## 七、重构后的质量守卫

### 7.1 自动化回归检测

迁移完成后，建立长期的质量守卫机制：

```bash
# 创建CI检查脚本
claude -p "创建一个重构回归检测脚本 scripts/refactor-check.sh，检查：
1. 是否有文件意外导入了已移除的依赖
2. 是否有文件仍在使用旧框架API
3. TypeScript编译是否通过
4. 所有测试是否通过
5. Bundle大小是否在合理范围内（与迁移前对比）

脚本应在CI/CD中运行，任何检查失败都应返回非零退出码。" \
  --allowedTools "Read,Write,Bash"
```

### 7.2 性能基准对比

```bash
claude -p "对比迁移前后的性能基准：
1. 使用 autocannon 或 wrk 对关键API端点进行压力测试
2. 对比响应时间（P50, P95, P99）
3. 对比内存使用
4. 对比冷启动时间
5. 输出对比报告，标注性能提升/退化的端点" \
  --allowedTools "Bash"
```

### 7.3 代码质量度量

```
> 请对迁移后的代码进行质量评估：
> 
> 1. 计算圈复杂度变化（迁移前后对比）
> 2. 检查TypeScript strict mode合规性
> 3. 检查是否有any类型逃逸
> 4. 统计代码行数变化（新增/删除/修改）
> 5. 检查是否有死代码引入
> 6. 输出质量评估报告，每项给出A/B/C/D评级
```

---

## 八、常见陷阱与解决方案

### 8.1 上下文窗口溢出

| 症状 | 原因 | 解决方案 |
|------|------|---------|
| Claude Code开始"忘记"之前的修改 | 会话上下文超过窗口限制 | 按模块分多个会话，用Memory传递状态 |
| 修改不完整，遗漏文件 | 影响范围判断不全 | 先用Grep全面扫描，生成变更清单 |
| 响应质量下降 | 上下文噪音过多 | 使用 `.claudeignore` 排除无关文件 |

### 8.2 迁移引入的隐蔽Bug

**典型案例**：Express的 `res.json()` 会自动设置Content-Type，但Fastify的 `reply.send()` 在某些情况下不会。

```bash
# 让Claude Code执行针对性检查
claude -p "检查所有迁移后的路由处理器，确认：
1. 所有JSON响应都设置了正确的Content-Type
2. 所有错误响应都有统一的错误格式
3. 文件上传响应的Content-Type正确
4. 流式响应（SSE）的处理方式正确

对每个检查点输出：检查结果 ✓/✗、涉及文件、问题描述" \
  --allowedTools "Grep,Read"
```

### 8.3 测试的测试——确保安全网本身可靠

```
> 检查我们的测试套件是否真正覆盖了迁移中的关键变更：
> 
> 1. 统计测试覆盖率，列出覆盖率低于80%的文件
> 2. 找出迁移中修改了但没有对应测试的文件
> 3. 对高风险文件（认证、支付、订单），建议补充测试用例
> 4. 确认集成测试覆盖了所有API端点
```

---

## 九、完整工作流检查清单

以下是执行大规模重构时的完整检查清单：

### 重构前
- [ ] 确认所有测试在当前代码库上通过
- [ ] 创建重构专用分支
- [ ] 在CLAUDE.md中记录重构目标和约束
- [ ] 使用Claude Code生成影响范围分析报告
- [ ] 建立性能基线

### 规划阶段
- [ ] 使用Plan Mode生成详细迁移计划
- [ ] 将计划分解为可独立验证的阶段
- [ ] 确认每个阶段的回滚策略
- [ ] 在Memory中记录关键决策

### 执行阶段
- [ ] 按计划逐阶段执行
- [ ] 每个阶段完成后运行测试
- [ ] 使用TaskList追踪进度
- [ ] 阶段性Git提交

### 验证阶段
- [ ] 全量测试通过
- [ ] 无残留的旧API调用
- [ ] TypeScript类型检查通过
- [ ] 性能基准对比完成
- [ ] 代码审查完成

### 收尾阶段
- [ ] 删除适配层和临时代码
- [ ] 更新项目文档
- [ ] 合并到主分支
- [ ] 清理重构分支

---

## 延伸阅读

- [Claude Code官方文档 - Plan Mode](https://docs.anthropic.com/en/docs/claude-code/plan-mode) — 了解Plan Mode的完整功能
- [Claude Code最佳实践 - 大型项目](https://docs.anthropic.com/en/docs/claude-code/best-practices) — Anthropic官方推荐的工作流
- [Fastify官方迁移指南](https://fastify.dev/docs/latest/Guides/Migration/) — 从Express迁移到Fastify的官方参考
- [Next.js App Router迁移指南](https://nextjs.org/docs/app/building-your-application/upgrading/app-router-migration) — Next.js官方迁移文档

---

## 参考来源

1. [Claude Code Documentation — Anthropic](https://docs.anthropic.com/en/docs/claude-code/overview) — Claude Code核心功能、Plan Mode、Memory系统的官方文档
2. [Claude Code Best Practices for Large Codebases](https://docs.anthropic.com/en/docs/claude-code/best-practices) — 上下文管理、多文件编辑、工作流优化的官方最佳实践指南
3. [Fastify Migration Guide](https://fastify.dev/docs/latest/Guides/Migration/) — Express到Fastify迁移的权威参考
4. [Next.js App Router Migration](https://nextjs.org/docs/app/building-your-application/upgrading/app-router-migration) — Pages Router到App Router的官方迁移路径

---

**训练营适用性评估**：

| 训练营类型 | 适用性 | 建议教学时长 | 说明 |
|-----------|--------|-------------|------|
| 企业内训（中级开发者） | ⭐⭐⭐⭐⭐ | 4-6小时 | 有真实项目可直接演练 |
| 线上付费课程 | ⭐⭐⭐⭐ | 3-4小时 | 需提供模拟项目供练习 |
| 高校软件工程课程 | ⭐⭐⭐ | 2-3小时 | 作为软件重构章节的实践内容 |
| 开发者大会工作坊 | ⭐⭐⭐⭐ | 2小时精简版 | 聚焦方法论和一个案例演示 |

**前置知识要求**：Claude Code基础使用经验6个月以上、Git熟练、了解至少一种Web框架。建议先完成入门篇和Skill开发篇的学习。

> [!tip] 51学通信知识星球
> **星主：爱卫生**（微信：gprshome201101）——公众号「51学通信」创办者，19 年通信行业运维与讲师经验，著有《GPRS网络信令实例详解》《EPC原理与实践》《5G核心网原理与实践》三本纸质书（各大电商平台有售）。
> **星球定位**：深耕 5G 核心网、IMS、NFV/AI、云原生等 ICT 领域，主打运维岗位与信令分析。
> **当前规模**：5200 篇主题 / 990 个回答，198 元/年。
> **加入福利**：加入星球后请加爱卫生微信，拉您进知识星球年度陪伴与答疑群——不限量回复您的各种问题，另有群内分享。
> **AI 加持**：51学通信知识星球已作为 skill 接入 WorkBuddy，使用 deepseek-4-flash 在海量星球帖子中精准找贴、找视频、找 FAQ 和案例，做总结、找文档和 PPT 等场景全覆盖。

![51学通信知识星球海报-扫码加入](https://wiki.500nian.com/images/zhixingqiu_qrcode.png)
