官方原文索引: Multi-file editing / Refactoring / Code Modernization
1. 核心架构与原理解析
Codex 的核心优势不是"生成代码片段",而是理解项目结构后协调跨文件修改。其内部执行流程:
关键能力:
| 能力 | 说明 | 示例 |
|---|---|---|
| 依赖图分析 | 识别文件间引用关系 | 改接口时找到所有调用方 |
| 拓扑排序 | 确定修改顺序 | 先改定义,后改实现 |
| 原子回滚 | 失败时自动撤销 | 测试失败则 git checkout |
| 增量验证 | 每步都跑测试 | 避免改完才发现全崩 |
2. 工程落地与代码示例
场景:大规模重构(CommonJS → ESM)
codex --full-auto
> 将项目中所有 CommonJS 的 require() 迁移为 ES Module import:
> 1. 修改 package.json 添加 "type": "module"
> 2. 更新所有 .js 文件中的 require → import
> 3. 更新 module.exports → export
> 4. 修复由此产生的路径解析问题
> 5. 运行 npm test 确保全部通过执行细节:
场景:提取公共逻辑
codex --full-auto
> 将 `src/user/service.ts`、`src/order/service.ts`、`src/payment/service.ts`
> 中重复的分页逻辑提取到 `src/shared/pagination.ts`:
> 1. 定义通用分页函数,支持 cursor 和 offset 两种模式
> 2. 替换三个文件中的重复代码为对新函数的调用
> 3. 补充提取后函数的单元测试
> 4. 运行全部相关测试提取前代码(重复):
// src/user/service.ts(重复片段)
async function listUsers(page: number, limit: number) {
const offset = (page - 1) * limit;
const users = await db.user.findMany({ skip: offset, take: limit });
const total = await db.user.count();
return { data: users, total, page, totalPages: Math.ceil(total / limit) };
}
// src/order/service.ts(重复片段)
async function listOrders(page: number, limit: number) {
const offset = (page - 1) * limit;
const orders = await db.order.findMany({ skip: offset, take: limit });
const total = await db.order.count();
return { data: orders, total, page, totalPages: Math.ceil(total / limit) };
}提取后代码:
// src/shared/pagination.ts
export interface PaginatedResult<T> {
data: T[];
total: number;
page: number;
totalPages: number;
}
export async function paginate<T>(
query: { skip?: number; take?: number; count: () => Promise<number> },
page: number,
limit: number
): Promise<PaginatedResult<T>> {
const offset = (page - 1) * limit;
const [data, total] = await Promise.all([
query.findMany({ skip: offset, take: limit }),
query.count(),
]);
return {
data,
total,
page,
totalPages: Math.ceil(total / limit),
};
}
// src/user/service.ts(替换后)
import { paginate } from '../shared/pagination';
async function listUsers(page: number, limit: number) {
return paginate(db.user, page, limit);
}场景:API 版本升级
codex --full-auto
> 将项目中所有 Axios 0.x 用法升级到 1.x:
> 1. 更新 package.json 中的 axios 版本
> 2. 处理废弃的 AxiosRequestConfig 类型变更
> 3. 处理拦截器 API 变更
> 4. 运行 npm install 和 npm test场景:数据库迁移重构
codex --full-auto
> 将用户表中的 phone 字段从 VARCHAR 改为 JSONB(支持多手机号):
> 1. 创建迁移脚本备份现有数据
> 2. 修改 Prisma schema
> 3. 生成并执行迁移
> 4. 更新所有读写 phone 的代码
> 5. 运行测试验证3. 场景深入:重构风险管理
风险矩阵
重构前检查清单
# 1. 确保 Git 干净
git status # 应该显示 working tree clean
git log --oneline -1 # 确认有 commit 点可回退
# 2. 创建备份分支
git checkout -b refactor/auth-module-backup
# 3. 回到主分支开始重构
git checkout main
git checkout -b refactor/auth-module
# 4. 启动 Codex
codex --full-auto
# 5. 重构完成后对比
git diff refactor/auth-module-backup4. 💡 核心避坑与最佳实践 (Takeaways)
- 重构前
git commit:跨文件修改一旦出错,手动回退成本极高 - 限定修改范围:用 "只改 src/ 目录" 防止 Agent 误入 node_modules 或配置文件
- 分阶段验证:不要等全部改完再测试,要求 Agent 每改完一个模块就运行相关测试
- 警惕隐式依赖:Codex 可能遗漏运行时依赖(如 Jest 配置、Babel 插件),重构后务必跑完整 CI
- 备份分支是保险:
git checkout -b backup/pre-refactor后再开始,最坏情况一键恢复 - 复杂重构用
/plan:先出完整方案,确认修改顺序和回滚策略后再执行