大型前端项目的文档驱动协作实践:从混乱到有序
本文基于一个真实企业级前端项目的协作经验,分享如何通过文档驱动的方式规范团队协作、统一代码风格、管理组件体系和保障交付质量。文中已脱敏处理,聚焦方法论和实践经验。
背景
在中大型前端项目中,随着团队规模扩大和业务复杂度提升,以下问题往往接踵而至:
- 代码风格不一致:不同开发者写出的代码风格迥异,命名、目录组织、分层逻辑各说各话。
- 协作规则口头化:约定存在于聊天记录和会议纪要中,新人入职无从查阅,规则随时间漂移。
- 组件能力不透明:公共组件散落各处,没有统一的能力说明,重复造轮子成为常态。
- 质量标准模糊:什么算"写完了"?测试覆盖到什么程度?文档更新到哪一步?缺乏可执行的门禁。
我们尝试用一套文档驱动的协作体系来解决这些问题。以下是核心实践。
一、统一协作规则入口:三文件同步机制
问题
不同 AI 工具(Claude、Gemini 等)和不同开发者需要遵循相同的协作规则,但规则散落在各处。
方案
建立三个等价的规则入口文件,内容保持严格一致:
| 文件 | 服务对象 |
|---|---|
CLAUDE.md | Claude Code |
AGENTS.md | GitHub Copilot / 其他 Agent |
GEMINI.md | Gemini |
三个文件只维护协作流程、质量门禁和执行约束,不重复维护具体代码风格细则。具体风格规范通过引用链接指向专门的规范文档。
关键约束:修改任一文件时必须同步修改另外两个文件,确保所有工具链看到的规则完全一致。
实践效果
- 新人入职时,阅读任一文件即可了解全部协作规则。
- AI 辅助编码时,所有工具遵循同一套规范,输出风格统一。
- 规则变更时有明确的同步责任,避免了"改了一个忘了一个"的问题。
二、代码风格规范的分层设计
问题
一个中型前端项目可能有数十个子目录、数百个文件,笼统的"代码规范"文档往往要么太泛(无法执行),要么太细(难以维护)。
方案:按职责分层拆分规范文档
我们将代码风格规范拆分为多个专项文档,每个文档聚焦一个职责领域:
docs/code-style/ ├── README.md# 总入口,引用各专项规范├── directories.md# 目录白名单与职责边界├── non-ui-ts.md# 普通 TS 非 UI 代码规范├── api.md# API 请求层规范├── services.md# 业务流程层规范├── stores.md# 状态管理层规范├── models.md# 数据模型规范├── cache.md# 缓存边界规范├── ui.md# UI 公共规范├── components.md# 组件规范├── pages.md# 页面与布局规范├── styles.md# 样式规范└── unit-tests.md# 单元测试规范核心原则
1. 业务实现优先靠近使用场景
页面专属的组件、hook、常量、类型、样式和工具函数,默认放在对应页面目录内。只有当某个能力被多个页面长期稳定复用后,才提取到外层公共目录。
// ✅ 正确:页面专属 hook 放在页面目录内src/pages/incident-ledger/hooks/useLedgerFilters.ts// ❌ 错误:尚未形成复用就提前抽象到公共目录src/hooks/useLedgerFilters.ts2. 不为"可能复用"提前抽象
这是一个常见的过度设计陷阱。我们的规则很明确:尚未形成复用的代码保留在当前业务上下文中。
3. 分层边界清晰
业务代码按api → services → stores → hooks → models → constants的职责分层,每一层有明确的职责边界:
| 层 | 职责 | 禁止事项 |
|---|---|---|
| API | 请求发送、DTO 转换 | 包含业务流程逻辑 |
| Services | 业务流程编排 | 直接操作 DOM 或 UI 状态 |
| Stores | 状态管理、持久化 | 包含请求逻辑 |
| Models | 数据模型定义、字段口径 | 包含 UI 渲染逻辑 |
| Pages | 页面组合、交互编排 | 承载可复用的业务逻辑 |
实践效果
- 评审时有明确的分层检查标准:“请求、流程、状态、模型、渲染是否混在同一文件?”
- 新增代码有据可依,减少了"放哪里都行"的主观判断。
- 历史遗留问题可以分阶段治理,每次改动让被触达的代码向规范收敛。
三、UI 统一规范:表单页与列表页
问题
表单页和列表页是企业级应用最常见的两种页面形态,但不同开发者实现的表单页在布局、操作区位置、搜索交互等方面差异很大。
方案
建立页面级 UI 统一规范,约束表单页和列表页的通用组合方案。
表单页规范要点:
- 独立路由中的创建、编辑、多分区表单
- 固定底部操作区
- 响应式表单分列(根据容器宽度自动派生一至四列布局)
列表页规范要点:
- 表格列表 + 搜索筛选 + 分页
- 列设置(用户自定义显示列)
- 页面级列表 store 统一管理状态
使用声明机制:
每个页面的文档开头必须声明采用的是哪种页面规范:
页面规范:表单页统一规范(docs/ui-standards/form-page.md)这样做的好处是:后续调整页面时,只需核实该页面声明的规范,而不是从头检查所有可能的规范。
四、全局能力的文档化管理
问题
项目中存在大量跨页面共享的全局能力(用户认证、HTTP 请求、状态管理、事件桥接等),这些能力的实现分散在各处,新人难以理解全貌。
方案
建立全局设计目录,为每个全局能力维护独立文档:
| 能力 | 文档内容 |
|---|---|
| 用户与权限 | 当前用户、mock persona、资源权限点、布局层入口权限校验 |
| 事件桥 | 承接平台事件并转发到应用消息通道 |
| 运行配置 | 解析运行模式、API 根地址、版本更新检查 |
| API 请求 | 请求入口、请求客户端、错误事件通知 |
| 全局状态 | local、ui、tag-views、user、reference-data 等 store |
| 响应式表单 | 根据容器宽度统一派生分列布局 |
每个全局能力文档必须声明:
- 覆盖的源码目录
- 被哪些页面或组件引用
- 参考的代码规范
- 测试入口
实践效果
- 处理全局能力时,先从索引定位主维护文档,再从文档定位源码和测试,形成完整的导航链路。
- 全局能力变更时,可以通过文档快速定位受影响的页面和组件。
五、组件体系的文档化
问题
公共组件的能力、适用场景和维护重点没有统一记录,导致重复开发或误用。
方案
为每个公共组件维护独立文档,记录:
- 功能说明:组件做什么,不做什么
- 适用场景:在哪些业务场景下使用
- 代码入口:源码目录位置
- 使用边界:组件的职责边界和限制
- 测试入口:对应的单元测试
- 维护重点:需要特别注意的点
以一个搜索列表组合组件为例:
| 维度 | 内容 |
|---|---|
| 功能 | 列表页顶部搜索、表头搜索、筛选摘要和列表工具栏组合 |
| 场景 | 列表页统一搜索交互 |
| 维护重点 | 草稿/已提交筛选边界、默认筛选重置、表头搜索注入 |
关键约束
- 组件文档只描述当前保留能力;组件移除时同步删除文档和入口索引。
- 处理公共组件时,先从组件索引定位文档,再从文档定位使用页面和测试入口。
六、单元测试的分类与门禁
问题
"测试覆盖率 80%"是一个常见的口号,但实际执行时往往流于形式:要么写了大量脆弱的实现细节测试,要么遗漏了关键的业务行为断言。
方案:功能行为测试 vs 静态边界测试
我们将单元测试分为两类,各有明确的测试对象:
功能行为测试:
- 验证稳定对外能力、状态变化、用户交互、错误结果和用户可观察副作用
- 围绕业务功能点和稳定契约断言,不绑定内部实现细节
- 测试名称应让读者看懂业务意图
// ✅ 好的测试:验证业务行为test('返回空数组当没有匹配的市场时',()=>{...})test('当 API Key 缺失时抛出错误',()=>{...})// ❌ 不好的测试:绑定实现细节test('调用了 fetchMarketList 函数',()=>{...})静态边界测试:
- 只落实代码风格规范中已明确规定的规则
- 扫描目录、依赖、命名、样式归属和禁止调用规则
- 不得自行增加规范中不存在的限制
测试组织
__tests__/ ├── boundaries/# 所有 src 改动的固定基线├── api-request/# 通用请求能力├── reference-data/# 引用数据├── incident-domain/# 事件模型├── table-list/# 列表组件├──...# 按功能模块分目录└── helpers/# 共享测试工具(不作为执行单元)关键规则:
- 测试执行的最小单位是功能模块目录,不是单个测试文件
boundaries/是所有src/改动的固定基线,必须执行- 页面和布局不编写功能行为测试(静态边界扫描除外)
质量门禁流程
改动代码 → 自动修复 + 规范 review → typecheck → lint → 定向测试 → 交付定向测试的范围根据影响链路确定,不默认扩大到全量测试。
七、文档维护的核心约定
1. 只保留最终状态
文档不保留中间过程、时间线、旧方案或已不适用功能。功能文档只保留最新有效内容和入口。
2. 入口驱动
每个目录(pages、models、components、global-design)都有一个README.md作为入口,记录索引和工作入口规则。处理任务时先从入口定位,不重新全仓探索。
3. 变更同步
代码、测试或文档发生变更时,必须同步更新相关文档:
- 功能代码完成移除后 → 同步处理相关文档、入口链接和过期说明
- 全局能力变更后 → 同步更新被影响的页面和组件文档
- 接口变更后 → 同步更新 mock 和模型文档
4. 声明边界
任务处理必须声明本次边界。发现边界外既有问题时,只记录到质量跟踪目录,不扩大本次修改范围。
八、与 AI 协作的最佳实践
在使用 AI 辅助编码时,这套文档体系发挥了额外的价值:
1. 规则前置
将协作规则写入CLAUDE.md等入口文件,AI 在每次会话开始时自动加载,无需重复说明。
2. 文档作为上下文
AI 处理任务时,先从入口文档定位相关规范和设计文档,再开始编码。这比口头描述需求更精确。
3. 渐进式收敛
AI 生成的代码也需要向规范收敛。我们的规则是:
- 新增代码必须严格遵守规范
- 被改动的旧代码,新增区域和修改区域也要满足规范
- 历史遗留问题分阶段治理,每次改动让代码向规范靠拢
4. 边界控制
明确告诉 AI 不要做什么比告诉它做什么更重要:
- 不处理边界外的页面、组件或模块
- 不顺手扩大改造范围
- 不为未列明的点自行增加测试
总结
文档驱动的协作体系不是要增加官僚流程,而是要让正确的做法成为阻力最小的做法:
- 统一入口:三个等价文件 + 引用链接,所有工具链看到相同规则。
- 分层规范:按职责拆分,每个文档聚焦一个领域,可独立维护。
- 页面形态标准化:表单页和列表页有统一的组合方案。
- 全局能力文档化:每个共享能力有独立文档和索引。
- 组件能力透明化:每个公共组件有功能、场景和边界说明。
- 测试分类明确:功能行为测试 vs 静态边界测试,各有清晰的测试对象。
- 变更同步机制:代码变更必须同步更新相关文档。
这套体系的核心理念是:文档不是代码的附属品,而是协作的基础设施。当文档足够好用时,开发者会主动查阅而不是凭记忆编码;当文档成为工作的入口时,它就不再是负担而是生产力工具。
本文基于实际项目经验整理,适用于 React + TypeScript + Ant Design 技术栈的中大型前端项目。具体规范内容可根据团队实际情况调整。