用Codex写前端?五组Skills让AI不再翻车
1. 为什么不能让 Codex 一口气写完整个前端先讲一个我自己的翻车经历。早先用 Codex 写前端的时候我干过一件特别偷懒的事把整个项目的需求往对话里一丢来一句“帮我写一个完整的任务看板前端”然后看着它一行一行往外吐代码。前 20 分钟确实很爽页面能跑组件也齐全但等我把功能往深了加问题就全冒出来了。1.1 一口气写完的三大坑上下文漂移、风格失忆、牵一发动全身第一个坑叫“上下文漂移”。Codex 本质上是基于上下文窗口推理的你让它一口气写 30 个文件前 10 个文件里定义的变量名、组件接口写到第 25 个文件的时候它可能已经记不清了。最常见的表现就是前面用UserCard后面变成UserProfileCard前面接口字段叫user_name后面又冒出个username。代码能跑但整个项目像是三个人各写各的拼起来的。第二个坑是“风格失忆”。哪怕你在需求里写明了“用 Tailwind不要写 CSS 文件”它写到后期也会偶尔给你插一段内联样式或者在某些地方用px固定宽度在另一些地方用rem。这种风格不统一的问题等代码量上去之后改起来真要命。第三个坑最致命叫“牵一发动全身”。一个完整前端里页面、组件、状态管理、API 请求、路由是强耦合的。Codex 一次性生成时它会默认这个项目里只有自己写的代码一旦你中途说“这个列表改成卡片布局”它只会去改列表组件完全意识不到还要同步调整相关的空状态、加载状态、测试用例和路由参数。结果就是改一处崩三处你比不写代码的时候还累。1.2 Skills 的本质把“大任务”变成“小合约”后来我开始琢磨怎么才能让 Codex 老老实实、一步一个脚印地干活。试过很多办法最后发现最有效的是把 Skills 当成“小合约”来用。Skills 说白了就是一组结构化的指令文件每个文件描述一个特定子任务的背景、约束、输入输出和验收标准。你可以把它理解成给新同事写的岗位说明书——不是告诉他“你要好好工作”而是告诉他“你的职责是这些你的产出长这样做完之后拿这个清单自检”。我用 Skills 重新规划前端开发之后Codex 的行为立刻就不一样了。它不再是那个“一口气憋个大招”的毛头小子而是一个按流程办事的熟练工拿到页面任务它先看组件清单一个组件一个组件实现拿到逻辑任务它先理数据类型再写 API 层最后才接 UI。每个阶段它都清楚自己该做什么、不该做什么输出质量肉眼可见地提升。注意Skills 不是提示词模板不是“请你写一个按钮组件”这种一次性指令。它的价值在于沉淀和复用——这个项目能用下个项目微调一下还能用。2. 五组 Skills 怎么划分页面、逻辑、测试、构建、质量想明白了要拆接下来的问题是按什么标准拆我见过有人按页面拆一个页面一套 Skills结果页面之间有大量公共逻辑Skills 之间互相打架。我也见过按技术栈拆的React 一套、Vue 一套但拆完发现同一个技术栈里页面和逻辑的差异远比跨技术栈大。2.1 划分原则按“变更频率”和“出错代价”拆我自己实践下来靠谱的依据是两个维度变更频率和出错代价。前端代码里页面的变更频率最高——产品经理三天两头改布局、换文案、调间距。逻辑状态管理、API 封装、业务规则变更频率中等但出错代价很高一个边界条件没处理线上就是白屏或者数据错乱。测试的变更频率跟着逻辑和页面走但它的核心价值在于“兜底”必须单独管。构建相关的代码变更频率最低但一出错就是全军覆没而且排查难度大也需要独立上下文。按照这个逻辑我最后沉淀出五组 Skills分组管什么不管什么出错代价page页面结构、组件实现、样式、布局、响应式数据获取、业务判断中logic类型定义、API 层、状态管理、错误处理UI 渲染、样式高test单元测试、组件测试、E2E 冒烟测试业务实现中build构建配置、环境变量、代码分割、产物分析业务代码极高quality代码审查、规范校验、提交信息、README具体功能开发低2.2 分组总览五组 Skill 的职责边界看到这个表你可能会问quality 这一组是不是多余的页面、逻辑、测试、构建已经覆盖了整个开发流程为什么还要单独拆一组出来原因很简单前四组保证的是“把东西做出来”quality 这一组保证的是“把东西做得像样”。Codex 写代码有一个特点单看每个模块都还行但合在一起看你会发现命名不一致、工具函数重复写了好几个、组件 props 设计得乱七八糟。这些小问题不致命但累积起来项目维护成本会飙升。必须有一个专门的关卡去做整体审查。我给每一组 Skill 都定了明确的边界。page 组只管“用户看得到的东西”它不负责决定数据从哪来logic 组只管“数据怎么流转”它不关心按钮是什么颜色test 组负责织一张安全网但它不重写业务代码build 组负责最后把产物体面地交出去但它不掺和业务逻辑quality 组则凌驾于前四组之上做交叉检查和收尾。这五个分组不是拍脑袋想出来的是我在几个真实项目里反复调整后的结果。最早我只分了三组UI、逻辑、构建后来发现测试没人管一改代码就提心吊胆于是加了 test再后来发现 Codex 提交的代码虽然能跑但质量参差不齐又加了 quality。现在这个结构基本稳定了我拿到一个新前端项目第一件事就是把这五组 Skills 的框架搭好再让 Codex 进场干活。3. 页面 Skills把界面拆成组件清单再动手页面 Skills 是我最早写的一组也是迭代次数最多的一组。一开始我写得太粗就一句“用 React 和 Tailwind 写一个任务卡片组件”结果 Codex 交出来的东西从组件命名到样式实现都不符合项目风格。后来我总结出一个规律页面类任务一定要让 Codex 先出清单再动手写代码。3.1 SKILL.md 里放什么内容以我之前做的“团队任务看板”项目为例page 组 SKILL.md 的核心内容大致是这么几块# Page Skill - 任务看板前端页面实现 ## 技术栈约束 - React 18 TypeScript只允许使用函数组件和 Hooks - 样式统一用 Tailwind CSS禁止书写自定义 CSS 文件 - 组件库使用项目内的基础组件禁止从零实现下拉、弹窗等通用交互 ## 开工前必须完成组件清单 - 列出当前页面涉及的所有组件 - 标注每个组件的 props 接口和职责边界 - 标注哪些组件是公共组件哪些是页面私有组件 ## 实现顺序 1. 先实现无状态展示组件 2. 再实现包含交互逻辑的组件 3. 最后组装成页面 ## 样式规范 - 使用 design-token 里定义的颜色和间距禁止自创色值 - 宽度单位统一使用 rem禁止使用 px - 必须处理 375px、768px、1280px 三档响应式 ## 验收清单 - 页面在三种断点下无横向滚动 - 所有交互元素都有 hover 和 focus 状态 - 无未使用的 import 和变量 - 组件职责单一无超过 200 行的组件为什么强调“先出组件清单”这个动作因为 Codex 在生成代码时有个毛病它会按自己的理解直接写而不是先想清楚整体结构。让它先列清单相当于强迫它做一次设计。你去看它列出的清单如果某个组件职责描述得含糊或者公共组件和私有组件混在一起你就能在写代码之前发现问题这时候纠错成本几乎为零。3.2 实操中让页面 Skills 真正生效的三个细节光有 SKILL.md 还不够我在实操里还摸出几个容易踩的细节。第一交互组件和展示组件要分开。展示组件只管渲染数据比如任务卡片、状态标签、用户头像交互组件管用户操作比如筛选器、拖拽排序、弹窗编辑。拆开之后Codex 写展示组件的时候不需要关心数据从哪来写交互组件的时候不需要纠结样式细节两边都轻松。第二样式规范里一定要写死设计令牌。前端页面最怕 AI 自由发挥颜色和间距一个页面出现十几种灰色是家常便饭。我在 SKILL.md 里直接给出一份design-token的约定主色#4F46E5、成功色#16A34A、危险色#DC2626间距只允许使用4px的整数倍。Codex 有了明确的颜色和间距锚点产出的页面视觉统一性会好很多。第三验收清单要让 Codex 自己执行。我之前总是写完代码让 Codex 再检查一遍但它经常敷衍了事说“看起来没问题”。后来我改成在验收清单里写明确的可执行验证项比如“检查是否有组件超过 200 行”“检查是否包含未使用的变量”逼着它自己跑 lint 或者逐项核查效果比一句“请检查代码质量”好得多。3.3 常见翻车场景布局和间距为什么会失控页面 Skills 用了这么久翻车最多的还是布局和间距。Codex 对“让这个区域水平居中”的理解经常是 “margin: 0 auto” 或者 “flex justify-content: center”结果在不同父容器下表现完全不一样。我的解决办法是在 SKILL.md 里增加一个“布局约定”小节明确说明复杂布局一律使用 flex 或 grid禁止使用 float 和绝对定位页面级容器统一用mx-auto max-w-7xl px-4组件间距使用gap而不是margin。这些约束看起来琐碎但正是这些琐碎的约定让 Codex 产出的页面从“看着还行”变成了“真的能上线”。4. 逻辑 Skills先定数据流再写业务代码页面写出来只是空壳真正的前端难点在逻辑层。我在用 Codex 的过程中发现如果你不单独给逻辑写一套规则它会把逻辑代码和 UI 代码搅成一锅粥——组件里直接发请求、业务判断写进 JSX、错误处理随手 throw 一个字符串这些都是常见的“自来熟”写法。4.1 逻辑 Skills 的核心三大模块我设计的 logic 组 Skills 固定管三块东西类型与接口、API 层、状态管理。类型与接口是地基。我会要求 Codex 在写任何逻辑代码之前先用 TypeScript 定义完整的领域模型比如任务Task有哪些字段、状态机的取值有哪些、接口返回的数据结构长什么样。这一步做好之后后面所有代码都基于这些类型来写类型不匹配的问题会大大减少。API 层是进出数据的大门。所有网络请求必须走统一的api/目录使用统一的请求实例配置好 baseURL、超时时间、鉴权头禁止在组件里直接调fetch或axios.get。每个 API 函数都返回类型化的 Promise错误统一抛ApiError。状态管理负责的是跨组件共享的数据。我用的是 Jotai所以在 SKILL.md 里定义的状态管理规范是原子化的数据写在store/目录下派生状态用selector完成异步更新走统一的异步流程。对于只有组件内部使用的状态明确要求用useState不要动不动就上全局 store。# Logic Skill - 业务逻辑与数据流实现 ## 核心原则 - 组件内禁止直接调用 fetch / axios必须通过 api/ 目录 - 业务判断禁止散落在组件里抽成纯函数放入 utils/ - 所有异步操作必须处理 loading、error、empty 三种状态 ## 数据类型先行 - 先绘制数据模型字段命名使用 camelCase - 接口返回的字段要在 api/ 层完成映射杜绝 snake_case 泄漏到组件层 ## 错误处理 - 网络错误统一抛出 ApiError包含 status、message、detail - 组件层只能通过 useEffect 或 Suspense 消费错误 - 禁止使用 console.log 调试统一使用项目内 logger ## 验收清单 - 类型定义覆盖所有接口返回结构和请求参数 - 无组件直接调用请求方法 - 无 any 类型除第三方库无类型声明的情况4.2 实操顺序为什么必须“数据先行”刚开始用 logic Skills 时我犯过一个错误让 Codex 按 UI 组件顺序逐个实现逻辑结果组件 A 定义了数据类型组件 B 又有自己的版本两边数据流完全对不上。后来我把 SKILL.md 里的流程改成了“数据先行”第一步让 Codex 输出完整的领域模型类型定义这是所有逻辑代码的共同语言第二步基于这些类型写 API 层函数第三步写状态管理和业务纯函数第四步才是让 UI 层消费这些数据和函数。这个顺序的好处是每一层的输入输出都是清晰的。API 层的输入是“用户要看哪个任务”输出是Task对象状态管理层的输入是 API 层的结果输出是组件可用的数据流。Codex 按照这个顺序来写就不会出现“为了一个列表页临时在组件里定义接口类型”这种土办法。4.3 让 Codex 把状态穷举完而不是只处理主流程我踩过一个特别深的坑Codex 写的逻辑代码总是只处理“happy path”也就是最顺利的那条路径。任务加载成功、列表有数据、用户点击正常这些场景它处理得很流畅但你要让它处理加载失败、列表为空、权限不足、接口超时它就比较敷衍经常是直接catch (e) {}静默吞掉。后来我在 LOGIC SKILL.md 里加了一条硬性要求“所有异步操作必须处理 loading、error、empty 三种状态缺一不可。”并且把它写进验收清单。Codex 收到这个约束之后写出来的代码明显更规范——列表加载时显示骨架屏、加载失败显示错误提示和重试按钮、数据为空时显示空状态文案。提示这一步非常关键。让 AI 写业务逻辑一定要把“异常路径”作为显式要求写进约束里否则它只会给你一个“看起来能用”的实现而真实用户永远会走你没想到的路径。5. 测试 Skills让 AI 给后续修改兜底测试这一组是我最晚加的但也是现在最离不开的。为什么单独拆出来因为我发现让 Codex 在同一个上下文里既写实现又写测试它总是先写完实现然后草草补几个测试用例应付你。这些测试跑起来全绿但仔细看全是“调用了一个函数没报错”这种毫无营养的断言。5.1 测试 Skills 的职责边界与配置我把 test 组 Skills 定义成“独立于业务实现的质检工序”它包含三个层面层级工具覆盖范围单元测试Vitest纯函数、工具函数、数据类型转换组件测试React Testing Library组件渲染、交互、状态展示E2E 冒烟测试Playwright核心用户流程登录、创建任务、完成任务配置上我固定了两条规则。第一所有测试文件放在被测模块旁的__tests__目录用xxx.test.tsx命名这样 Codex 在改某个组件的时候能很容易看到对应的测试第二覆盖率阈值定在 80%分别在lcov报告里统计语句、分支、函数、行覆盖率跑不到就视为失败。5.2 实操如何让 Codex 写出有价值的测试让 AI 写测试最大的问题是它只会写“成立的测试”。所谓成立的测试就是找个输入跑一遍断言输出不是undefined就当作完成。这种测试对维护毫无价值。我在 TEST SKILL.md 里的对策是要求 Codex 针对每个函数列出至少三个用例——正常输入、边界输入、异常输入并且每个用例必须使用具体的输入值和期望输出禁止使用模糊断言。比如测试一个formatTaskTime(timestamp: number): string函数你让它写三个用例传一个有效时间戳断言返回格式化的日期字符串传 0 或负数断言返回空字符串或抛出异常传一个超出范围的极端时间戳断言不会崩溃且格式正确。有了这类具体要求Codex 写测试的认真程度会提升好几个档次。组件测试也一样。我要求每一个交互型组件必须覆盖以下场景初次渲染时各个状态是否正确展示用户执行核心操作后回调函数是否被调用且参数正确异步操作成功和失败时的 UI 反馈。这三个场景写全比写十来个空泛的“渲染无报错”有用得多。5.3 避坑指南AI 写测试常见的三个歪招和 Codex 磨合测试 Skill 的过程中我遇到过三类特别典型的“应付式测试”这里直接列出来。第一类是“全覆盖但全无效”。AI 会生成十几个测试文件每个测试文件里都有好几个用例你以为覆盖得不错了仔细一看全是expect(element).toBeInTheDocument()没有任何交互和断言。第二类是“过度 mock”。为了不让测试碰到真实依赖AI 会把所有东西都 mock 掉包括它自己刚写好的模块导致测试结果完全失真。第三类是“污染全局状态”。测试里改变了一些 module 级变量跑完不清理后面的测试用例全被带偏。针对这三类问题我的 TEST SKILL.md 里写死了三条禁令禁止出现没有行为的断言禁止 mock 当前被测模块内部依赖所有测试必须在afterEach中清理副作用。有了这三条Codex 的测试质量稳定了很多。6. 构建 Skills把产物体面地交出去构建阶段是很多 AI 编程工具最糟糕的环节之一。原因很好理解构建报错往往不是业务代码的问题而是环境变量、依赖版本、打包配置这些“周边因素”导致的而 Codex 在写业务代码时的上下文里根本没有这些信息。它连报错日志都没看全就开始瞎猜“可能是这个依赖版本有问题”然后胡乱升级依赖反而把项目搞坏了。6.1 构建 Skills 的核心内容我的 build 组 Skills 专注于四件事构建配置、依赖管理、产物质量、环境区分。构建配置包括 Vite 配置文件里的别名、代理、打包 chunk 规则。依赖管理的关键是锁定依赖版本我明确要求 Codex 只通过包管理器的lock文件检查依赖树禁止直接修改package.json里的版本号。产物质量指的是构建完成后必须检查dist/目录的大小、chunk 数量、各个页面的入口文件、是否有异常大的资源。环境区分是要求 Codex 使用import.meta.env或process.env按环境区分配置接口地址、上传域名、埋点开关都不能写死。# Build Skill - 构建流程问题排查与产物优化 ## 判断步骤必须按顺序执行 1. 完整读取报错日志提取关键错误信息 2. 检查 package.json 和 lock 文件确认依赖状态 3. 检查 vite.config 和 tsconfig 配置 4. 定位报错涉及的具体文件和依赖关系 ## 依赖管理规则 - 禁止直接修改依赖版本号 - 报错指向依赖问题时先提供完整的 error stack 和运行环境 - 更新依赖后必须执行完整构建验证 ## 产物质量要求 - 构建成功后在 dist/ 中找到各路由对应的 html 入口 - 检查 chunk 数量单个 chunk 超过 200KB 需要拆分 - 确认静态资源引用路径正确无 404 ## 多环境配置 - 开发、测试、生产环境必须使用独立的环境变量文件 - 接口地址、上传域名等配置必须在环境变量中禁止硬编码6.2 让 Codex 排查构建报错的标准姿势我自己总结出了一个比较管用的配合方式遇到构建报错时不直接把报错丢给 Codex而是先做一步预处理——把报错信息、复现步骤、当前运行环境Node 版本、包管理器版本、系统架构整理成一封“病历报告”再发过去。原因很简单Codex 的上下文窗口是有限的你把完整且结构化的问题描述给它它才有足够的信息做推断如果你直接复制一大段终端日志它会被无关信息干扰或者被日志截断影响判断。我在 BUILD SKILL.md 里专门加了一节“问题描述模板”要求 Codex 在处理构建问题时先按模板输出自己的理解报错出现在哪个阶段依赖安装、编译、打包、部署前检查、涉及哪些文件、可能的触发条件是什么。这个步骤看起来额外耗时但它能帮 Codex 在动手之前理清思路排查成功率明显提高。6.3 构建产物体积失控让 Codex 自己分析前端构建还有一个常见问题是产物越来越大首次访问越来越慢。这个问题的排查思路也是 AI 擅长的分析产物构成。我让 Codex 跑构建之后把dist/目录的文件大小列表拉出来用可视化的依赖分析插件检查哪个第三方库占了大头。Codex 能快速识别出“某个表格组件引了完整包”“某个图表库没按需加载”这类典型问题然后建议用按需导入或动态导入拆分。实际项目里我遇到过最夸张的一次一个详情页首屏加载了 1.2MB 的 JS其中一个图表库占了 800KB最后改成按需导入后直接降到 300KB。这个优化如果凭我自己在密密麻麻的依赖关系里找至少要折腾一上午Codex 配合 build Skill 十几分钟就搞定了。7. 质量 Skills最后一道代码审查关卡前面四组把开发流程跑通了但你会发现代码虽然能跑、有测试、能构建整体上还是有点“野”。命名不一致、重复代码、组件边界混乱、注释和代码对不上……这些问题单个看不致命但累积到一定量维护效率会急剧下降。所以第五组 Quality Skills 是专门做“整体把关”的。7.1 让 Codex 以“资深 Review 者”身份工作Quality 组最常见的用法是在所有功能开发完成后让 Codex 扮演一个资深前端工程师的角色对全项目做一次代码审查。我的 Quality SKILL.md 里定义了一个审查清单审查维度具体检查项一致性命名风格、API 封装规范、错误处理方式是否统一简洁性是否存在重复代码、冗余组件、无用依赖健壮性关键路径是否有异常处理、边界条件是否覆盖可维护性组件是否过大、职责是否清晰、类型是否明确和直接说“帮我 review 一下代码”相比把审查维度拆细之后Codex 能给出更具体的问题列表。我实测下来它能发现不少真问题某个组件在其他地方已有类似实现、某个 API 函数既没有统一错误处理也没有取消机制、某个动画库其实完全可以用纯 CSS 实现。这些问题靠人工自查很容易漏掉。7.2 让 Codex 输出“问题清单”而不是“直接改代码”这里有一个很重要的操作细节质量审查阶段不要让 Codex 直接改代码而是让它先输出一份“问题清单”每条问题标注严重级别和建议修复方案由你来决定改哪些、怎么改。为什么这么设计因为 Codex 在自由发挥“修问题”的时候经常会好心地改变原有实现逻辑造成不必要的回归风险。它自己改出来的代码又需要重新测试、重新审查等于把刚才的流程再走一遍。相比之下问题清单的方式更符合“人做决策、AI 做执行”的原则你来判断哪些问题值得修、哪些可以保留然后逐条指派给它做定向修复。7.3 附带的规范收尾README 和提交信息Quality Skills 里还可以挂一些收尾性质的内容比如让 Codex 生成项目的 README、更新启动文档、规范 git commit message。这些内容不涉及核心逻辑但对项目交付体验影响不小。我在实际项目里最后会让 Codex 根据最终代码状态重写一份 README把启动命令、环境变量说明、技术栈列表都写清楚省去自己回忆和整理的时间。commit message 我也在 Quality Skills 里定了一个模板type(scope): subject比如feat(task): add drag sort。让 Codex 在提交前跑一遍git diff --stat概括本次改动然后按模板生成提交信息。这样提交历史看起来非常干净回滚和排查问题都方便。8. 常见问题与排查技巧实录Skills 这套玩法用了几轮之后我也积累了一些解决问题的经验。这里挑几个高频问题集中说一下希望能帮你少走弯路。8.1 Codex 不遵守 Skills 怎么办最常遇到的问题就是明明写了 SKILL.mdCodex 还是按自己的想法乱来。我的排查思路有三步。先确认 Skill 文件是否真的被正确加载了很多 CLI 工具对 Skill 目录的命名、路径有严格要求比如必须放在.codex/skills/或者~/.codex/skills/放错位置等于白写。再确认 SKILL.md 里的指令是否足够明确像“请尽量遵循规范”这种话 AI 根本不会认真执行必须改成“禁止使用 px”“必须在组件清单完成后才能开始写代码”这种可验证的命令式语句。最后确认上下文里是否混入了旧规则有时候前面对话里已经出现了和 Skills 冲突的指令AI 会优先听最近的消息。8.2 Skills 之间互相冲突怎么办多组 Skills 同时存在时偶尔会打架。比如 page 组让 Codex 在组件里直接展示数据logic 组又禁止组件里直接发请求。遇到这种情况我在 SKILL.md 里加了一个“优先级声明”logic 组的约束优先于 page 组build 组的约束优先于一切业务代码。这样冲突出现时Codex 就有明确的裁决依据而不是随机挑一个听。8.3 上下文不够用怎么办Codex 的上下文窗口有限项目一大对话一长它就记不住前面聊了什么。我的做法是“任务缓存”每个阶段结束后把结论沉淀进一个项目备忘录文件比如“已完成组件清单”“已定义类型清单”“已确认的接口字段”下一个阶段开始时先让它读这个备忘录再干活。这样做比让它硬记整段对话可靠得多。8.4 什么时候该自己上手写最后说一个很多人都忽视的问题Skills 再完善Codex 也不是万能的。我的经验是核心业务逻辑里涉及复杂规则的部分、对性能要求极高的渲染路径、设计稿里那种特别精细的视觉还原这三类任务还是自己动手更靠谱。Skills 的真正价值不在于让 AI 全包而在于把你定义好的流程跑熟练让机械性的工作量减少 80%把省下来的精力集中在真正需要人判断的地方。实测问题原因解决方式Skill 文件加载无效目录结构不符合工具约定检查 Skill 目录位置和命名确认文件名规范AI 无视样式约束指令写得太软将约束改成可验证的规则如“禁止 px”测试写了等于没写断言太宽松要求每个函数至少三个用例含边界和异常构建报错排查不准问题信息不完整按“病历报告”模板提供完整上下文上下文过长导致遗忘对话历史超限使用项目备忘录沉淀阶段性结论我个人现在最深的体会是把前端拆成五组 Skills表面上是给 AI 写说明书实际上是在逼我自己把开发流程想清楚。AI 有没有变强不好说但我的项目比之前规范了不止一个量级。最后再分享一个小技巧每组 Skills 的末尾都留一个“验收清单”小节让 Codex 在完成任务后逐项自检这一步能帮你省掉大量的低级返工。