从 PRD 到上线:SpecKit 如何让 AI 真正参与前端交付
你有没有遇到过这种情况:
产品给了一份 PRD,你让 AI 帮忙拆任务,它能说出一堆“看起来正确”的建议;设计稿来了,你让 AI 写页面,它又开始猜组件结构;等到代码写完,再让 AI Review,它只能对着局部代码提一些泛泛而谈的建议。
问题不一定出在 AI 不够强。
很多时候,是我们给 AI 的输入太散了。
需求、设计、代码、Review、测试、上线,每个环节都有上下文。但这些上下文没有被结构化,AI 就只能凭经验补空白。补得准时很惊艳,补不准时就是返工。
这就是我想介绍 SpecKit 的原因。
SpecKit 不是某个单一工具,而是一套规范化的 AI 协作开发流程。它的核心目标是:把从需求到上线的每个环节,都变成 AI 能读懂、能执行、能验证的标准输入输出。
下面我会用一个“用户管理模块”的例子,拆一遍 SpecKit 在前端开发里的完整使用方式。
SpecKit 解决的不是写代码,而是减少猜测
传统开发流程里,AI 最容易翻车的地方通常有四类:
- PRD 写得太口语化,AI 不知道哪些是硬需求。
- 设计稿缺少结构说明,AI 只能按视觉截图猜组件。
- 开发任务没有边界,AI 容易一次改太多。
- Review 只看局部代码,很难发现流程级问题。
SpecKit 的做法很朴素:
- 需求拆解模板化。
- UI 还原标准化。
- 组件开发任务化。
- Code Review 清单化。
- 上线交付可验证。
也就是说,它不是让 AI “随便发挥”,而是把 AI 放进一条有约束的工程流水线里。
整体流程可以理解成这样:
flowchart TD
A["PRD 产品需求文档"] --> B["需求拆解"]
B --> C["技术任务清单 + 风险分析"]
C --> D["UI 还原"]
D --> E["组件结构 + 样式规范"]
E --> F["组件开发"]
F --> G["功能代码 + 测试用例"]
G --> H["Code Review"]
H --> I["修复建议 + 改进代码"]
I --> J["测试与上线"]
上图可以理解为 SpecKit 的主线:先把目标说清楚,再让 AI 在需求、设计、开发、评审和部署之间传递结构化上下文。
关键点是:每一步都有明确的输入和输出。
这会显著降低 AI 的不确定性。
第一步:把 PRD 写成 AI 能拆的格式
很多团队的 PRD 其实是给人看的,不是给 AI 执行的。
人可以根据经验补上下文,AI 也会补,但它补出来的东西未必符合你的项目约束。
所以 SpecKit 的第一步,是把 PRD 写成结构化格式。
以用户管理模块为例,一个比较适合 AI 拆解的 PRD 可以这样写:
# 需求:用户管理模块
## 业务背景
管理员需要管理系统用户,包括查看、创建、编辑、删除、权限分配等功能。
## 功能需求
### 1. 用户列表页
- 展示用户名、邮箱、角色、状态、创建时间
- 支持按用户名、邮箱搜索
- 支持按角色、状态筛选
- 支持分页,每页 20 条
- 操作包括查看详情、编辑、删除、重置密码
### 2. 创建用户
- 必填字段:用户名、邮箱、密码、角色
- 选填字段:真实姓名、手机号、部门
- 用户名:3-20 字符,字母数字下划线
- 邮箱:标准邮箱格式
- 密码:8-20 字符,包含大小写字母和数字
### 3. 编辑用户
- 可修改除用户名外的所有字段
- 密码可选修改,为空则不修改
### 4. 删除用户
- 二次确认弹窗
- 删除后刷新列表
- 不能删除当前登录用户
## 非功能需求
- 列表加载时显示 skeleton
- 表单提交时按钮 loading
- 接口报错统一处理
## 接口清单
- GET /api/users
- GET /api/users/:id
- POST /api/users
- PUT /api/users/:id
- DELETE /api/users/:id
- POST /api/users/:id/reset-password
这个 PRD 的重点不是“写得漂亮”,而是每个字段都可以被 AI 映射到技术任务。
比如:
- “分页每页 20 条”会进入列表状态管理。
- “密码为空则不修改”会进入编辑表单 schema。
- “不能删除当前登录用户”会进入操作列逻辑。
- “按钮 loading”会进入 mutation 状态处理。
这比一句“做一个用户管理”稳定得多。
第二步:让 AI 输出技术任务清单
有了结构化 PRD,就可以让 AI 做需求拆解。
我通常会把 Prompt 写得很明确:
请根据以下 PRD,进行技术任务拆解。
【PRD 内容】
{粘贴 PRD}
【拆解要求】
1. 识别需要开发的页面和组件
2. 每个页面或组件列出:
- 技术实现要点
- 依赖的 API
- 需要的状态管理
- 表单校验规则
- 异常处理场景
3. 识别技术难点和风险点
4. 给出开发任务优先级
5. 估算开发工作量
【技术栈】
- React 18 + TypeScript
- Ant Design 5.x
- React Query
- React Hook Form + Zod
理想输出不是一段“开发建议”,而是一份可执行的任务清单:
| 任务 | 优先级 | 工作量 | 依赖 |
| --- | --- | --- | --- |
| API 层开发 | P0 | 0.5 天 | 后端接口 ready |
| 用户列表页 | P0 | 1 天 | API 层 |
| 搜索筛选组件 | P1 | 0.5 天 | 列表页 |
| 创建用户表单 | P1 | 1 天 | API 层 |
| 编辑用户表单 | P1 | 0.5 天 | 创建表单 |
| 删除确认逻辑 | P2 | 0.5 天 | 列表页 |
| 重置密码功能 | P2 | 0.5 天 | API 层 |
这张图对应的就是需求拆解阶段:左边是结构化 PRD,右边是按优先级整理后的技术任务。
这一步非常关键。
它把“让 AI 写代码”之前的模糊需求,变成了“让 AI 按任务实现”的明确上下文。
从我的经验看,AI 协作质量提升最快的地方,不是在代码生成阶段,而是在任务拆解阶段。
因为任务拆得越清楚,后面越不需要赌模型理解力。
第三步:先定类型,再写接口
SpecKit 会鼓励先把类型和 API 层固定下来。
这一步很适合 AI 做,因为输入已经足够明确,输出也容易验证。
例如用户类型可以先这样定义:
export interface User {
id: string;
username: string;
email: string;
realName?: string;
phone?: string;
department?: string;
role: 'admin' | 'user' | 'guest';
status: 'active' | 'inactive';
createdAt: string;
updatedAt: string;
}
export interface UserListParams {
page: number;
pageSize: number;
keyword?: string;
role?: string;
status?: string;
}
API 层则需要把 PRD 里的接口清单转成明确函数:
export const getUserList = (
params: UserListParams,
): Promise<{ list: User[]; total: number }>;
export const getUserDetail = (id: string): Promise<User>;
export const createUser = (data: CreateUserParams): Promise<User>;
export const updateUser = (
id: string,
data: UpdateUserParams,
): Promise<User>;
export const deleteUser = (id: string): Promise<void>;
export const resetPassword = (id: string): Promise<void>;
为什么要先做这一层?
因为它是后续页面、表单、测试的共同契约。
如果类型没定,AI 后面生成的组件很容易每个文件都猜一套字段名。最后你会得到很多看似合理、但无法集成的代码。
第四步:列表页要把状态边界说清楚
用户列表页看起来是普通 CRUD,但这里藏着很多容易遗漏的细节:
- 搜索条件是否进 URL?
- 搜索后是否回到第一页?
- 接口失败后是否保留旧数据?
- 表格 loading 和空状态怎么处理?
- 分页参数来自 URL 还是组件内部状态?
这些都应该在任务清单里提前说明。
例如:
const [searchParams, setSearchParams] = useSearchParams();
const { data, isLoading, refetch } = useQuery({
queryKey: ['userList', searchParams.toString()],
queryFn: () =>
getUserList({
page: Number(searchParams.get('page')) || 1,
pageSize: 20,
keyword: searchParams.get('keyword') || '',
role: searchParams.get('role') || '',
status: searchParams.get('status') || '',
}),
});
这里有一个很实用的规则:
只要用户刷新页面后仍然希望保留的状态,就优先放进 URL。
对后台系统来说,搜索、筛选、分页通常都属于这类状态。
搜索表单也可以被拆成独立组件:
const handleSearch = (values: SearchFormValues) => {
setSearchParams({
...values,
page: '1',
});
};
注意这里的 page: '1'。
这是很典型的业务细节:筛选条件变化时,如果不重置页码,用户可能会停留在一个不存在数据的页。
这种细节越早写进 Spec,AI 越不容易漏。
第五步:表单复用要明确“相同”和“不同”
创建用户和编辑用户有大量相似逻辑。
但它们也有几个关键差异:
- 创建时密码必填,编辑时密码可选。
- 创建时用户名可输入,编辑时用户名禁用。
- 编辑时需要初始值回填。
- 编辑时空密码不提交或表示不修改。
这类场景最忌讳一句“复用表单组件”就结束。
更好的 Spec 是直接描述组件接口:
interface UserFormProps {
mode: 'create' | 'edit';
initialData?: User;
onSubmit: (data: UserFormData) => Promise<void>;
}
然后再把校验规则写清楚:
const createUserSchema = z
.object({
username: z
.string()
.min(3, '用户名至少 3 个字符')
.max(20, '用户名最多 20 个字符')
.regex(/^[a-zA-Z0-9_]+$/, '用户名只能包含字母、数字、下划线'),
email: z.string().email('请输入正确的邮箱格式'),
password: z
.string()
.min(8, '密码至少 8 个字符')
.max(20, '密码最多 20 个字符')
.regex(/(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/, '密码必须包含大小写字母和数字'),
confirmPassword: z.string(),
role: z.enum(['admin', 'user', 'guest']),
realName: z.string().optional(),
phone: z.string().regex(/^1[3-9]\d{9}$/, '请输入正确的手机号').optional().or(z.literal('')),
department: z.string().optional(),
})
.refine((data) => data.password === data.confirmPassword, {
message: '两次输入的密码不一致',
path: ['confirmPassword'],
});
这里还有一个简单但有用的判断标准:
如果两个表单 80% 一样,但校验规则有差异,先复用组件,再分离 schema。
不要为了“复用”把所有逻辑揉进一堆 if (mode === 'edit')。
SpecKit 不是鼓励过度抽象,而是鼓励把差异显式写出来。
第六步:UI 还原不要只给截图
很多人让 AI 还原设计稿时,只丢一张截图。
这当然能生成页面,但稳定性一般。
更好的做法是让 AI 先拆组件结构:
根据这个设计稿,帮我拆解组件结构。
【要求】
1. 识别页面包含哪些组件
2. 说明组件嵌套关系
3. 判断组件是否可复用
4. 给出建议文件结构
用户列表页可以拆成:
UserListPage
├── PageHeader
├── SearchForm
├── UserTable
│ ├── StatusTag
│ ├── RoleTag
│ └── ActionButtons
└── Pagination
CreateUserModal
└── UserForm
EditUserModal
└── UserForm
然后再提取样式规范:
export const colors = {
primary: '#1890ff',
success: '#52c41a',
warning: '#faad14',
error: '#ff4d4f',
textPrimary: '#262626',
textSecondary: '#8c8c8c',
border: '#d9d9d9',
background: '#f0f2f5',
};
export const spacing = {
xs: 8,
sm: 12,
md: 16,
lg: 24,
xl: 32,
};
把设计稿拆成 UI、组件树和 design tokens 后,AI 生成的代码会更接近工程里的真实边界。
这一步的价值是把“视觉还原”变成“设计 token + 组件结构 + 代码实现”。
AI 不再只是看图写 CSS,而是在明确边界内生成页面。
第七步:开发阶段用测试约束 AI
SpecKit 里我最推荐的一种写法,是先让 AI 写测试,再让 AI 实现代码。
例如表格组件可以先写测试:
describe('UserTable', () => {
it('应该正确渲染用户列表', () => {
const users = [mockUser1, mockUser2];
render(<UserTable data={users} />);
expect(screen.getByText(mockUser1.username)).toBeInTheDocument();
expect(screen.getByText(mockUser2.username)).toBeInTheDocument();
});
it('点击编辑按钮应该触发回调', () => {
const onEdit = jest.fn();
render(<UserTable data={[mockUser1]} onEdit={onEdit} />);
fireEvent.click(screen.getByText('编辑'));
expect(onEdit).toHaveBeenCalledWith(mockUser1);
});
it('删除当前用户时应该禁用删除按钮', () => {
render(<UserTable data={[mockUser1]} currentUserId="user-1" />);
expect(screen.getByText('删除')).toBeDisabled();
});
});
然后再让 AI 根据测试实现组件:
根据以下测试用例,生成 UserTable 组件代码。
【要求】
1. 所有测试通过
2. 使用 TypeScript
3. Props 类型完整
4. 不引入额外抽象
先有测试,再让 AI 补实现,等于给模型加了一条可验证的轨道。
这样做有两个好处:
- AI 的输出更聚焦。
- 你有一个客观验证标准。
没有测试时,我们只能说“看起来能用”。有测试时,我们可以说“这个行为已经被覆盖”。
第八步:Code Review 要给维度,不要只说“帮我看看”
“帮我 Review 一下代码”是一个很弱的 Prompt。
AI 会提建议,但建议很可能散。
SpecKit 更推荐把 Review 维度固定下来:
请 review 以下代码,从这几个维度评估:
1. 代码质量
- 是否符合项目规范
- 是否有代码坏味道
- 是否有潜在 bug
2. 性能
- 是否有不必要的 re-render
- 是否有内存泄漏风险
- 是否需要优化
3. 安全
- 是否有 XSS 风险
- 敏感信息是否泄露
4. 可维护性
- 代码是否易读
- 是否有重复代码
- 注释是否充分
请给出具体修改建议,必要时用 diff 展示。
这类 Review 更容易得到可执行的结果。
比如:
- return <Table dataSource={data} />;
+ return <Table dataSource={data || []} />;
或者:
- }, []);
+ }, [userId]);
Review 不是终点,它应该和测试、部署监控一起组成上线前的质量门。
真正有价值的 AI Review,不是“这段代码整体不错”,而是能指出具体位置、具体风险和具体改法。
SpecKit 的收益来自“可重复”
在源文档的案例里,用户标签功能从 PRD 到上线被拆成了 6 个阶段:
- 需求拆解:30 分钟。
- UI 还原:1 小时。
- 组件开发:1.5 天。
- Code Review:30 分钟。
- 测试:2 小时。
- 上线:10 分钟。
整体大约 2 天完成,而传统方式可能需要 4-5 天。
这个数字不一定适用于所有团队,但背后的逻辑很值得参考:
| 指标 | 传统流程 | SpecKit 流程 | 改善方向 |
|---|---|---|---|
| 需求理解 | 靠反复沟通 | 结构化拆解 | 减少歧义 |
| 代码生成 | 靠上下文猜测 | 按任务实现 | 减少返工 |
| Review | 人工逐行看 | AI 先筛一遍 | 提高效率 |
| 测试 | 后补测试 | 先写行为约束 | 更容易验证 |
| 上线 | 临时检查 | 清单化交付 | 降低遗漏 |
SpecKit 的核心收益不是“AI 一次生成完所有代码”。
它真正提高的是协作可重复性。
当流程稳定后,你可以把它用于多个类似业务模块,比如:
- 用户管理
- 角色权限
- 标签系统
- 审批流
- 配置后台
- 数据看板
这些需求都不是算法难题,但细节多、协作链路长,非常适合用 SpecKit 降低沟通成本。
什么时候不适合用 SpecKit?
也不是所有需求都适合。
SpecKit 更适合:
- 标准 CRUD 需求。
- 重复性较高的业务模块。
- 多人协作项目。
- 有明确设计稿和接口约束的前端页面。
- 需要沉淀团队规范的项目。
不太适合:
- 探索性原型。
- 高度创新的交互实验。
- 需求还没有成形的早期想法。
- 只需要几十行代码的小改动。
如果需求本身还在探索,过早套 SpecKit 反而可能增加负担。
我的建议是:先从一个小而完整的需求试点。
比如一个后台列表页,一个设置表单,或者一个标签管理模块。
等团队跑顺之后,再把 Prompt 模板、代码规范、测试模板、Review 清单逐步沉淀下来。
最后:让 AI 从“会写代码”变成“会参与交付”
AI Coding 最容易被误解成“让 AI 多写点代码”。
但真实项目里,代码只是交付链路的一部分。
需求是否清楚、组件边界是否合理、状态是否可恢复、测试是否覆盖、Review 是否有效、上线是否有清单,这些才决定最终质量。
SpecKit 的价值就在这里:
它不是替代开发者,而是把开发者的判断前置,把 AI 的能力放进可验证的流程里。
如果你想在团队里更稳定地使用 AI 协作,可以从这 5 件事开始:
- 把 PRD 改成结构化模板。
- 让 AI 先输出技术任务清单。
- 每个任务都写清输入、输出和验收标准。
- 复杂组件先写测试,再生成实现。
- Review 固定维度,并要求给出可执行修改建议。
当这些动作成为习惯后,AI 就不再只是一个“代码补全工具”。
它会变成需求拆解、UI 还原、组件开发、Review 和上线检查里的协作者。
这才是 SpecKit 真正想解决的问题。
欢迎在评论区聊聊:
- 你现在会让 AI 参与需求拆解吗?
- 你团队里最适合 SpecKit 的模块是什么?
- 你更想先标准化 PRD、UI 还原,还是 Code Review?