用Codex写前端别贪多:5组Skills拆分法,让AI从补全器变成工程工具
2026/9/9 7:22:42 网站建设 项目流程

用 Codex 写前端,最忌讳的就是贪。很多人上来就是一句“帮我把这个后台管理系统做完”,然后 Codex 吭哧吭哧生成几百个文件,不出五分钟就有了一个“看起来很完整”的前端项目,结果一跑全是报错:缺依赖、漏 import、类型对不上、接口字段猜错,修起来比从零写还难受。我的做法完全相反:我会提前准备好 5 组 Skills,把页面、逻辑、测试和构建拆成一组组独立、可复用的指令,每一次只让 Codex 完成一个明确的小交付物。这样它不是在“写整个前端”,而是在一条流水线上逐个加工零件。这个思路尤其适合用 Codex 做真实项目、而不是做 demo 的开发者。

我下面会把这 5 组 Skills 的具体定位、文件组织方式、实际调用顺序,以及踩坑后的排查方案完整讲一遍。如果你正准备用 Codex 写前端,或者已经发现“让 AI 一口气写完”这条路走不通,这套拆法可以直接抄作业。

1. 为什么我不让 Codex 一口气写完整个前端

1.1 Codex 的“一口气”和人的“一口气”完全不一样

人写前端的时候说的“一口气写完”,其实脑子里已经有一个隐含的计划:先搭路由,再写组件,再补状态管理,最后跑一把构建。这个计划是跟着代码量同步推进的,每写一个文件,编译器、lint、浏览器都在给你反馈。

但 Codex 不是这样。你让它一口气写,它实际上是在一次推理里尽可能多地生成文本,它没有办法真正“执行”一遍自己的代码,也没有办法在生成过程中停下来问自己:这个函数我上一条消息里是不是已经定义过了?这个 API 返回的字段我有没有猜对?它只能靠模型记忆和统计概率往前推。文件多了之后,前面写的代码和后面写的代码经常互相矛盾,这是必然的,不是运气问题。

所以“别让 Codex 一口气写完整个前端”不是因为它能力不行,而是因为缺少反馈闭环。任何复杂任务,只要反馈周期太长,质量就不可控。你让 Codex 写一个页面,它写完了你可以马上看 render 效果,这是一个短反馈;你让它把全套页面、全部逻辑、一堆测试和构建配置一起写完,反馈周期长到你根本不知道哪里先错的,最后只能整盘推翻。

1.2 一次只做一类事,本质上是把“上下文预算”留给关键信息

Codex 的上下文窗口虽然一直在变大,但上下文不是用来装代码垃圾的。真正有价值的上下文应该是:项目结构说明、接口契约、设计约束、当前要完成的任务边界、验收标准。如果你让它在一次对话里把三十个页面都写出来,上下文里塞满了一半重复的 import 和样式代码,等到写核心逻辑的时候,模型已经在大量无关信息里迷路了。

我经过大量实操后发现,一次只让它做一个页面、一个 hook、一组测试,Codex 的回答质量和稳定程度会显著上升。原因很简单:每个子任务的上下文占用小,它能把注意力集中在当前这个交付物上;而且我可以在每个任务结束后,把这次生成的代码“固化”到项目里,再开新任务。这样每个任务之间是干净的,不会出现“第 13 个页面引用了第 2 个页面里的一个组件,但那个组件在第 7 次重写时已经被删掉了”这种连环事故。

1.3 拆分的原则:按交付物拆,不要按代码类型拆

很多人拆任务时会说“先写 HTML,再写 JS,再写 CSS”,这是按文件后缀拆,不是按交付物拆。前端开发的真实单位应该是一个“可验证的结果”:一个能渲染的页面、一组通过测试的逻辑、一份能出包的构建配置。我拆分的标准就是:每个子任务的输出必须能单独被验证。

页面技能的输出可以靠浏览器预览验证;逻辑技能的输出可以靠 typecheck 和单测验证;构建技能的输出可以靠 build 产物验证;测试技能的输出可以靠 vitest 跑绿验证。凡是不能独立验证的任务,都不要丢给 Codex 单独执行,因为你会很快失去对质量的判断力。

2. 5 组 Skills 具体怎么拆

2.1 先搞清楚 Skills 在 Codex 里到底是什么

我这里说的 Skills,不是 IDE 插件市场里的那种扩展,而是一段可以被 Codex 在特定任务时主动加载的 Markdown 指令。通常一个 Skill 就是一个目录,里面有SKILL.md,文件头写上名字、描述、适用场景,正文写上执行步骤、输出要求、需要遵守的约束和常见的反面案例。

Codex 的原理是:你给它一个任务,它会先看项目里的AGENTS.md或者skills目录,根据任务描述去匹配最合适的 Skill,把它当作“操作手册”来执行。这有点像我给一个新同事一份“标准作业流程”:你不用每一次都从零解释怎么验收,Skills 帮你把经验沉淀下来。

我把前端的活拆成 5 组 Skills,覆盖了从零开始一个项目到交付的完整链路,也是我最近几个项目里一直在用的组合。

组别Skill 名称负责范围输出物验证方式
1ui-page-builder页面结构和 UI 组件TSX 文件、样式文件、组件 props浏览器渲染、Storybook
2logic-state-manager状态、接口调用、业务逻辑hooks、store、API service、类型定义tsc、单元测试
3test-case-writer单测、集成测试、边界场景测试文件、mock、测试数据vitest 跑绿
4build-engineering构建配置、环境变量、打包优化配置文件、脚本、CI 片段build 出包、产物检查
5review-refactor代码审查、修复、重构diff 变更、重构计划、问题清单lint、typecheck、全量回归

2.2 第一组:页面骨架与 UI 组件 Skills

这组 Skill 只负责一件事:让 Codex 把页面框架和 UI 组件搭出来。在这个环节,我不希望它去写任何业务逻辑,也不要它调接口、管全局状态。视觉上看起来能用就行,数据全部通过 props 传进来,事件全部用回调抛出去。

我常用的ui-page-builder指令里会有这样几条硬性要求:

  • 所有业务判断必须抽到组件外部,组件内部只做展示;
  • 样式优先使用项目已有的 design token,不允许随手写死颜色;
  • 每个组件必须声明 props 类型,不接受any
  • 交互反馈(loading、空态、错误态)必须有对应的 UI 状态,哪怕先用占位符。

这个 Skill 的价值在于:页面是前端里最容易产生“视觉噪声”的部分。如果让 Codex 在写页面的同时又去补状态逻辑,它往往会为了“省事”把useEffect和数据请求直接写进组件里,页面看起来能跑,但后续改需求就是灾难。把页面和逻辑拆开,等于强行让 Codex 遵守“组件层不产生副作用”的规矩。

2.3 第二组:状态管理与业务逻辑 Skills

第二组logic-state-manager是我认为最核心的 Skills。前端项目的复杂程度,主要就体现在逻辑层:接口请求的时序、状态字段的派生、错误重试、权限判断,这些东西才是以后维护时最容易翻车的地方。

我要求 Codex 在做逻辑时遵循这么几条:

  • 业务逻辑先抽纯函数,能不用 hook 表达就不用 hook;
  • API service 层统一收口,禁止页面里直接调用fetchaxios
  • 所有异步操作必须处理loadingsuccesserror三种状态;
  • 状态变更必须有明确的边界,谁写谁读要能一眼看出来。

实操的时候我是这么用的:先给 Codex 看接口文档或者类型定义,让它把 service 层写出来;然后再看页面 props,让它把 hooks 补齐;最后再把 hooks 接到页面上。每一步之间我都会让tsc --noEmit跑一遍,类型能过,说明接口之间的契约基本对齐了,再往下走。

这一步里最容易犯的错误是让 Codex“自由发挥”接口返回结构。只要后端文档没给清楚,它一定会自己猜字段名,猜错了后面全串味。所以我都会在指令里明确写:API 字段有歧义时,必须先把疑问列出来,不许猜。

2.4 第三组:测试用例与边界场景 Skills

测试这个环节,很多人会下意识忽视,觉得“让 AI 写代码已经很辛苦了,测试让它随便补补就行”。但我要说,测试才是 Codex 项目里真正的安全网。没有测试,你很难判断 Codex 刚才那次改动到底是修好了还是引入了新问题。有了测试,你每次让它改完东西,跑一遍就知道有没有把之前的功能干碎。

我用test-case-writer时,Codex 不只是简单给函数写两个 happy path 用例,我会强制它覆盖这些场景:

  • 数据为空的空态展示;
  • 接口返回错误的 error 态;
  • 长时间 loading 的边界;
  • 用户快速点击导致的重复提交;
  • 权限不足时的行为;
  • 接口字段缺失或类型不符的容错。

同时测试里要写好 mock,不能真的发请求。Codex 对vi.mock和 Testing Library 的waitFor这些 API 已经很熟,只要给它清晰的指令,它写出来的测试质量通常不差。真正需要人盯的是:它有没有为了测试通过而把业务逻辑写错。所以我要求测试用例先写,再写实现,至少要在同一个任务里让 Codex 自己跑一遍vitest

2.5 第四组:构建配置与工程化 Skills

构建和工程化是“代码能跑”和“项目能上线”之间最后一道坎。Codex 如果只写业务代码,它是不会替你关心分包策略、环境变量、浏览器兼容、CDN base 路径这些问题的。但这些配置恰恰是前端项目里最容易因为一个小错误就导致整个线上挂掉的部分。

build-engineering这组 Skill 我会用来处理:

  • Vite / Webpack 的构建配置;
  • TypeScript 的路径别名、tsconfig的 strict 配置;
  • 环境变量读取和运行时注入;
  • 构建产物的分包策略、chunk 大小控制;
  • 部署时的 base 路径和资源前缀;
  • CI 里的buildtesttypecheck脚本组织。

这个 Skill 不只是给 Codex 一份配置模板,我还会要求它解释每个关键配置是干什么的。比如manualChunks为什么要单独分割reactreact-dom,因为这两个包基本不会变,单独分包能提高缓存命中率,减少用户二次访问的加载时间。这样它改配置的时候才会谨慎,而不是随手加一个optimizeDeps就跑了。

2.6 第五组:审查、修复与重构 Skills

最后一组不是写新功能,而是干脏活:审查 Codex 自己写的代码,发现问题,定位问题,修问题。前端项目用 AI 写多了以后,最常见的状态是“功能都能跑,但代码不能看”:一个组件好几百行、状态全用 useState 堆、到处都是重复逻辑。

我用review-refactor指令时,会明确告诉 Codex:

  • 先跑一遍linttypechecktest,把客观问题收集起来;
  • 再按“高危险、中危险、低危险”给问题分级;
  • 高危险问题先修,比如状态更新后不触发渲染、资源没有释放、内存泄漏;
  • 中低危险问题输出成清单,不要一股脑全改;
  • 重构时不许改变对外接口和页面效果。

这套 Skill 的核心精神是“小步重构”。很多人在 Codex 写的代码太乱之后,会让它“把这个文件重写一遍”,结果 Codex 一激动把半个模块全改了,回归测试一片红。我宁可让它在一次任务里只重构一个函数、一个组件,改完跑一遍测试,再继续下一个,稳得多。

3. 落地实操:从项目初始化到交付的完整流程

3.1 项目里怎么组织 Skills 文件

Skills 要起作用,不只是写一堆 Markdown 扔到项目里就行,还需要合理的组织方式。我通常会在项目根目录下建一个skills文件夹,再配合AGENTS.md给 Codex 一个入口说明:

your-project/ ├── AGENTS.md ├── src/ │ ├── pages/ │ ├── components/ │ ├── hooks/ │ ├── services/ │ └── test/ ├── skills/ │ ├── ui-page-builder/SKILL.md │ ├── logic-state-manager/SKILL.md │ ├── test-case-writer/SKILL.md │ ├── build-engineering/SKILL.md │ └── review-refactor/SKILL.md └── package.json

AGENTS.md里我会写这么一段:

## 工作方式 开始任何任务前,先阅读 skills 目录下的相关指令。 如果一个任务跨越多个 Skills,拆成多个步骤执行。 每完成一个步骤,必须运行对应的验证命令,再进入下一步。

这个文件相当于给 Codex 立规矩:它是“拆任务干活”,而不是“一股脑全干”。没有这段话,Codex 即使看到了 Skills 目录,也可能因为你的 prompt 太长而忽略掉。

每个SKILL.md我建议用统一的格式,方便 Codex 解析。比如ui-page-builder/SKILL.md

--- name: ui-page-builder description: 适合创建前端页面骨架和 UI 组件。 trigger: 当用户要求写页面、组件、布局时使用。 --- ## 目标 生成可渲染的 TSX 页面或组件,不处理业务逻辑。 ## 步骤 1. 确认路由和页面布局。 2. 创建组件,props 必须有明确类型。 3. 样式使用设计系统的 token。 4. 状态和接口调用全部留给 logic-state-manager。 ## 约束 - 禁止在组件里调用 fetch、axios 等请求方法。 - 禁止引入未使用的组件。 - 禁止使用 any 类型。 ## 验证 运行 npm run typecheck

3.2 实际调用顺序:页面 → 逻辑 → 测试 → 构建

有了 Skills,实际干活的时候顺序就非常重要。我大概的流程是这样:

第一步,我会先让 Codex 初始化项目骨架,但并不是让它生成全部页面。我会先给它一个路由清单,比如后台管理系统有登录页、仪表盘、用户列表、用户详情、设置页,然后只让它做第一个页面。

第二步,用ui-page-builder让 Codex 生成登录页的页面结构。这个页面里所有交互先写成空函数,表单提交之后只console.log当前值。这一步的目标不是“能用”,而是“长得像”。

第三步,用logic-state-manager让它补登录逻辑。我会给它后端的登录接口契约,比如POST /api/auth/login返回{ token, user }这种结构。Codex 需要基于契约先写services/auth.ts,再写hooks/useLogin.ts,把表单数据和接口调用接起来。

第四步,跑tsc和 lint。如果类型出问题,就让 Codex 根据报错修正,保证当前这个页面是完整可用的。

第五步,用test-case-writer给登录逻辑和登录页写测试。到这里,登录这一个页面才算是“做完”了。然后我再以同样的流程推进用户列表、用户详情等其他页面。

这个过程看起来每一步都很小,似乎很慢,但实际体验是:每一块功能做完之后都是稳的,后面不会再返工。慢反而是快。

3.3 把验证命令做成自动闸门

Skills 不只是写给人看的,也要让 Codex 有明确的“完成标准”。我喜欢把每个项目的验证命令统一抽象成几个脚本:

{ "scripts": { "typecheck": "tsc --noEmit", "lint": "eslint . --ext ts,tsx", "test": "vitest run", "test:watch": "vitest", "build": "vite build", "verify": "npm run typecheck && npm run lint && npm run test && npm run build" } }

然后每次让 Codex 完成一个小任务时,我都会要求它必须把对应的验证命令跑一遍。比如做完页面逻辑,就运行npm run typecheck;补完测试,就运行npm run test;最后要交付了,就运行npm run verify

这样做事的好处是,Codex 的“完成”不是它自己觉得完成,而是有客观标准。它能跑通verify,说明类型、静态检查、单测、构建四个环节都过了。遇到问题它也会自己先修一轮再交给我,而不是丢一堆红色报错让人类来收拾。

4. 常见问题与排查技巧实录

4.1 常见问题:Codex 改 A 的时候把 B 改坏了

这个问题几乎每个人都会遇到,特别是任务拆得不够细的时候。比如你说“帮我调整一下登录页的布局”,Codex 一高兴,把登录逻辑也重写了,结果原本正常的 session 续期逻辑也被干掉了。

我的排查思路是:先看 diff,确认它到底改了哪些文件。然后,Codex 改代码时属于“嫌疑文件”的改动,如果不在本次任务范围内,就回滚;如果必须改,单独开一个新任务处理。

要减少这个问题,最好的办法是在每个 Skill 里都加一条约束:一次只改指定文件,其他文件不允许动。代码里会有一些跨模块的隐式依赖,Codex 不一定能感知到。它觉得自己很聪明地“顺手重构”了一下,其实就是制造 bug 的起点。

4.2 常见问题:Skills 不生效,Codex 好像没读

很多时候不是 Skills 没写对,而是你给 Codex 的指令本身太长了,或者新的指令把 Skills 里的约束覆盖了。Codex 会优先听你最近说的一句话,如果你在 prompt 里说“顺便把这个组件的样式也调一下”,它就可能跳过 Skill 里的“只做展示”约束。

我的处理方式是把 Skills 里的关键约束放到AGENTS.md里,作为项目级规则。同时我在对话里的指令尽量简洁,不要和 Skill 冲突。比如我只要说“用 ui-page-builder 创建用户列表页”,剩下的细节让它自己去读SKILL.md

另外,SKILL.md 里的 description 字段很重要,Codex 靠这个字段来判断什么时候应该加载它。description 里一定要写清楚“触发场景”,比如“当用户要求创建页面、组件、布局时使用”,这样它才能精准匹配。

4.3 常见问题:构建过了,但浏览器里页面空白

这种情况经常发生在用 Codex 写 SPA 时。一个最容易踩的坑是路由模式:项目用的是 history 路由,但部署环境没有做 history fallback,刷新二级页面时直接 404 或白屏。Codex 写业务代码时根本不会考虑部署配置,它只会“按约定”把路由配好。

所以我在build-engineering这个 Skill 里会特别加一条检查清单:路由模式、基础路径、静态资源引用方式、服务端有没有做 history fallback。这属于“Codex 不提醒你就不会做”的典型工程问题。

4.4 常见问题:测试永远跑不过,但看起来代码没问题

测试挂掉先别急着让 Codex 改测试。常见的几个原因:

  • 测试里 mock 的路径和实际代码 import 的路径对不上;
  • 异步操作没有用waitForfindBy,导致断言执行时组件还没渲染完;
  • 组件里用到了浏览器 API,测试环境没做对应 mock;
  • vi.mock写在vi.hoisted外面,导致变量提升问题。

我的排查顺序是:先让 Codex 解释一下这个测试在测什么、依赖了哪些 mock,再让它把测试拆分得更小,一次只测一个行为。如果还是搞不定,就先把测试改成“只测纯函数”,绕开 DOM 渲染这一层,至少保证核心逻辑有保护网。

4.5 如何让 Codex 选择“重写”而不是“打补丁”

Codex 有很强的“打补丁”倾向,尤其是在一个文件已经被改了很多轮之后。你让它修一个小 bug,它往往会在原有函数里加一层 if,结果代码越来越臭。

我现在的做法是在review-refactorSkill 里定了一个规则:当一组函数或一个组件长度超过 200 行,或者嵌套层数超过 4 层,Codex 必须先给出“重构计划”,而不是直接改。重构计划要说明:拆成哪几个子模块、怎么保持行为不变、会影响哪些测试。我看完计划之后,才会让它动手。

这样做的本质是把“重写”从冒险变成受控。它依然有主动重构的空间,但每一步都要先交代清楚,避免把项目越改越乱。

5. 这些组合用下来的一点个人体会

我自己也经历过“让 Codex 一口气写完整个前端”的阶段,结果是我花了一个晚上来修它生成的错误,最后实在忍无可忍,把生成的代码几乎全删了重新写。后来我开始尝试拆分 Skills,从最开始的草稿,到慢慢沉淀成现在这 5 组,才真正感觉到 Codex 是一个可用的工程工具,而不仅仅是一个自动补全器。

最大的变化是心态。以前我让 Codex 写代码,担心的是“它会不会偷偷埋雷”;现在我发现,只要任务边界清晰、验证命令跑得勤,Codex 生成的代码质量能稳定维持在“需要 review,但不需要返工”的水平。它写烂代码的频率大大降低,就算写了,也会被测试和类型检查拦下来,而不是上线了才被用户发现。

最后分享一个小经验:Skills 不是一次写完就完事的,它是会“生长”的。每次你发现 Codex 在某类任务上犯了同样的错误,就把这个错误写进对应 SKILL.md 的“反面案例”里。比如有一次它在多个页面里重复写了同一个请求逻辑,我就在 logic 的约束里加了一条“公共请求必须抽到 service 层,禁止在页面间复制”。下次它再遇到类似任务,就会主动规避。

这套 5 组 Skills 的拆法,对我来说已经成了所有前端项目的默认启动配置。你不需要完全照抄,可以先从“页面”和“逻辑”两组开始,跑通一次项目后,再把测试和构建逐渐加进来。只要记住一个核心原则:让 Codex 每次只写完一个能验证的小块,别让它一口气吞下整个前端。这样它写代码,你管节奏,效率会比手写和全自动都高。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询