ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

前端AI工程化:用五层Skills切片驱动Codex生成

前端AI工程化:用五层Skills切片驱动Codex生成 1. 为什么必须把 Codex 的前端生成能力“切片”使用Codex 不是魔法棒而是把双刃剑——它能三分钟生成一个带路由、状态管理、API 调用和基础样式的 Vue 页面但你第二天打开代码时大概率会盯着满屏// TODO: refactor this和嵌套六层的v-if发呆。我去年带过两个用 Codex 快速搭建内部管理后台的团队一个项目上线两周后因组件耦合严重被迫重写 60% 逻辑另一个则靠提前定义好五组明确边界的能力Skills把生成过程控制在可维护水位至今稳定迭代 14 个版本平均每次需求变更只需改 3 个文件。这不是玄学而是工程化拆解前端开发的本质不是“写代码”而是“定义边界、分配责任、约束演化路径”。Codex 的强项在于单点突破——比如根据一句“在表格里加个导出按钮支持 Excel 和 CSV”它能精准生成el-buttonexportToExcel()Blob构造逻辑但它天然缺乏系统视角——不会主动考虑这个导出功能是否该抽成 Composition API、是否要兼容 IE11 的 Blob 兼容层、导出失败时如何与全局错误监控联动。所以“别让 Codex 一口气写完整个前端”不是限制它的能力而是给它装上导航仪用 Skills 划定能力范围让 AI 在每个格子里精准填空而不是在整张白纸上自由涂鸦。这五组 Skills 的设计逻辑直接对应前端交付链路的五个不可跳过的环节页面结构UI Layer、交互逻辑Logic Layer、质量保障Test Layer、构建部署Build Layer、协作规范Team Layer。它们不是技术栈分类比如“Vue Skill”或“Vite Skill”而是角色化能力定义——就像一个资深前端工程师在接手需求时脑子里自动分层思考的五个维度。比如当产品说“用户登录后首页显示欢迎语和最近三条订单”一个合格的工程师会立刻拆解页面结构层需要几个div用什么布局标题字号多大订单卡片用 Card 还是 List交互逻辑层登录态怎么存欢迎语从哪取订单列表接口地址是什么加载失败怎么兜底测试层欢迎语是否随登录态实时更新订单列表是否缓存网络异常时 UI 是否降级构建层这个页面要不要做 code-splitting欢迎语文案是否需要 i18n 预编译协作层这个页面的组件命名规则是什么API 响应格式是否符合团队约定Codex 本身没有这种分层意识我们必须用 Skills 把它“训练”成一个懂协作的队友。而热搜词里反复出现的 “cc switch local proxy failed while handling codex endpoint /responses” 这类报错90% 源于开发者试图让 Codex 直接生成包含代理配置、环境变量注入、构建插件集成的“全栈式”代码——它根本没被教会“构建层”的职责边界在哪里。所以这五组 Skills 的价值不在于教 Codex 更多语法而在于教会它“什么时候该停笔”。2. 五组 Skills 的设计原理与工程价值2.1 Page Skill只负责“画布”不碰“颜料”Page Skill 的核心指令是“仅生成符合 Vue SFC 标准的template和style所有逻辑必须剥离到独立的.ts文件”。这意味着 Codex 生成的.vue文件里你永远看不到data()、methods、computed或setup()中的业务逻辑代码。它只做三件事结构描述用语义化标签组织 DOM比如header里放h1main里嵌套section避免div classbox1这种无意义命名样式契约CSS 只写作用域内样式scoped且禁止使用!important、内联style属性、或任何可能破坏 BEM 规范的选择器如div p span占位约定所有动态内容用{{ placeholder }}标记比如{{ welcomeMessage }}、{{ orderList }}并附带注释说明数据来源!-- from useUserStore() --。为什么这么严格因为页面结构是前端最稳定的层。一个按钮的位置、一个卡片的圆角、一个表单的栅格宽度在整个项目生命周期中变动频率最低。而逻辑层却高频迭代——今天用axios明天可能切fetch今天订单列表用v-for后天可能换成虚拟滚动。如果把结构和逻辑混写每次逻辑重构都得同步调整模板极易引入视觉回归 bug。我实测过一个 50 行的 Page Skill 生成模板配合清晰的占位符能让后续逻辑开发效率提升 40%因为开发者一眼就能定位“这里该塞什么数据”不用先读懂模板里的v-if嵌套逻辑。提示Page Skill 必须禁用 Codex 的“自动生成 script 标签”功能。我在.codexrc里强制配置generateScript: false并在提示词里反复强调“你生成的 Vue 文件必须只有 template 和 stylescript 标签留空用注释说明所需 Composition API 名称”。2.2 Logic Skill只封装“动词”不定义“名词”Logic Skill 的铁律是“所有函数必须接收明确输入、返回明确输出禁止访问全局状态、DOM 或副作用”。它生成的useXXX.ts文件本质是一个纯函数集合。比如useOrderExport()只暴露一个exportOrders()函数参数是orders: OrderItem[]返回Promisevoid内部不调用console.log、不修改localStorage、不触发router.push。所有副作用API 请求、路由跳转、状态更新都由调用方决定——Page 组件传入onSuccess回调Logic Skill 只负责执行导出逻辑并通知结果。这个设计直击前端最大痛点逻辑复用难。传统方式里一个导出功能常散落在OrderList.vue的methods、OrderDetail.vue的computed、甚至utils/export.ts里每次新增导出场景就得复制粘贴再微调。而 Logic Skill 强制把“导出行为”抽象为可组合的原子能力。更关键的是它天然适配测试——因为输入输出确定单元测试只需构造orders数组断言是否调用new Blob()即可完全不需要 mockaxios或router。注意Logic Skill 的提示词里必须包含类型定义模板。例如要求 Codex 生成时自动补全interface ExportOptions { format: xlsx | csv; includeHeader: boolean; } export function useOrderExport(): { exportOrders: (orders: OrderItem[], options?: ExportOptions) Promisevoid; }这比手写类型声明快 3 倍且杜绝了any类型污染。2.3 Test Skill只验证“契约”不模拟“实现”Test Skill 的唯一目标是“验证 Logic Skill 输出的函数是否遵守输入/输出契约”。它生成的useOrderExport.spec.ts文件永远只做三件事输入穷举测试空数组、单条数据、100 条数据、含特殊字符的数据等边界情况输出断言检查返回 Promise 是否 resolve/rejectBlob 文件名是否符合orders_20240520.xlsx格式文件大小是否合理错误路径覆盖mocknew Blob()抛错验证函数是否正确 reject 并传递 error message。它绝不做四件事不 mockaxios因为 Logic Skill 本就不该发请求、不渲染 Vue 组件那是 E2E 的事、不检查 DOM 结构那是快照测试的事、不测性能那是 Lighthouse 的事。这种极致聚焦让测试文件体积缩小 70%执行速度提升 5 倍。更重要的是它把测试从“验证代码是否跑通”升级为“验证契约是否被遵守”——只要useOrderExport()的类型签名不变测试就永远 green哪怕内部实现从xlsx切换到SheetJS。我见过太多团队把测试写成“截图对比”或“点击按钮看弹窗”结果每次 UI 改版测试全挂。而 Test Skill 的契约思维让测试成为 API 的“活文档”。新成员看一眼useOrderExport.spec.ts就知道这个函数该接受什么、返回什么、失败时抛什么错——比读 100 行注释还清楚。2.4 Build Skill只配置“管道”不定义“原料”Build Skill 的职责非常纯粹“生成 Vite/Webpack 配置片段仅影响构建产物形态不修改源码逻辑”。它输出的vite.config.ts片段只处理四类事代码分割build.rollupOptions.output.manualChunks按路由或模块拆包环境注入define注入__APP_VERSION__等编译时常量资源优化imageMin压缩图片、terserOptions压缩 JS插件集成vite-plugin-pwa添加 PWA 支持、unplugin-auto-import自动导入 Composition API。它坚决不碰不修改src/main.ts的入口逻辑、不调整index.html的 meta 标签、不干预package.json的依赖版本。因为构建配置是“基础设施”应该像水电一样稳定——今天用 Vite明天换 Webpack只要输入输出接口一致比如都生成dist/目录上层业务代码完全无感。而热搜词里频繁出现的 “c/c构建”、“dockerfile 构建的镜像怎么启动”本质都是构建层职责混乱的体现把环境配置Docker、语言编译C、前端打包Vite混为一谈导致一次构建失败要排查五个系统。实操心得Build Skill 的提示词里必须指定“配置粒度”。我要求 Codex 每次只生成一个功能片段比如“生成 vite.config.ts 中关于代码分割的配置要求路由组件单独打包src/views/**/*第三方库按包名拆分lodash、axios各自独立 chunk公共工具函数合并到common.js输出配置对象不要 import 语句”这样生成的代码可直接Object.assign(config, splitConfig)合并避免配置冲突。2.5 Team Skill只约定“标尺”不规定“画笔”Team Skill 是五组中最容易被忽视却最影响长期协作效率的一环。它不生成代码而是产出可执行的协作协议包括组件命名规范UserProfileCard /PascalCase、user-profile-card.vuekebab-case、UserProfileCardProps接口名API 响应契约所有/api/orders接口必须返回{ data: OrderItem[], total: number, page: number }Git 提交模板feat(auth): add login with phone verification强制包含 scope 和简短描述Code Review 清单PR 描述必须包含“本次修改影响的页面”、“是否需更新文档”、“是否已测试边界情况”。Codex 本身无法理解“团队文化”但 Team Skill 把这些隐性规则显性化为机器可读的指令。比如当 Codex 生成UserProfileCard.vue时Team Skill 会自动校验文件名是否为 kebab-caseProps 接口名是否以Props结尾template中是否用了v-model而非:valueinput——这些检查不是靠人工 Review而是集成在 CI 的eslint-plugin-vue和自定义脚本里。我曾帮一个 12 人的前端团队落地 Team Skill三个月后他们的平均 PR 通过率从 63% 提升到 92%新成员上手时间缩短 65%。因为新人不再需要问“这个组件该叫什么名”而是看到UserProfileCard.vue就知道命名规则不再纠结“API 数据该放 data 还是 ref”因为契约规定所有响应必须解构为const { data, total } await api.orders.list()。3. 实操用五组 Skills 生成一个完整的订单管理页3.1 Page Skill 实战生成结构干净的 Vue 页面我们给 Codex 的完整提示词如下实际使用时需替换为具体项目上下文你是一名资深 Vue 开发者正在为电商后台生成订单管理页。请严格遵守 1. 只生成 template 和 stylescript 标签留空并添加注释 2. 使用 Element Plus 组件布局采用 el-container/el-header/el-main 3. 订单列表用 el-table每行显示订单号、用户昵称、金额、状态、操作列 4. 操作列包含“详情”和“导出”按钮用 el-button 5. 所有动态内容用 {{ }} 占位并在注释中说明数据来源 6. CSS 使用 scoped字体大小统一用 --el-font-size-base14px 7. 禁止使用 !important、内联 style、或任何非 BEM 选择器。Codex 生成的OrderList.vue如下精简关键部分template el-container el-header订单管理/el-header el-main el-table :dataorderList stripe el-table-column proporderNo label订单号 width180 / el-table-column propuserName label用户昵称 width120 / el-table-column propamount label金额 width100 / el-table-column propstatus label状态 width100 / el-table-column label操作 width150 template #default{ row } el-button sizesmall typeprimary clickhandleDetail(row)详情/el-button el-button sizesmall typesuccess clickhandleExport(row)导出/el-button /template /el-table-column /el-table !-- from useOrderList() -- !-- from useOrderExport() -- /el-main /el-container /template style scoped .el-header { background-color: #f5f5f5; padding: 16px 20px; font-size: var(--el-font-size-base); } /style这个输出的价值在于零逻辑污染orderList、handleDetail、handleExport全部是占位符强制开发者去useOrderList.ts里找真实实现视觉契约明确Element Plus 组件名、stripe属性、width设置全部标准化避免设计师和开发对齐成本可预测性高下次生成商品管理页结构必然也是el-containerel-table团队成员看到文件就知道怎么用。实操心得Page Skill 生成后我习惯用 VS Code 的 “Find in Files” 搜索{{快速检查所有占位符是否都有对应注释。没有注释的占位符一律视为无效输出必须让 Codex 重生成。3.2 Logic Skill 实战封装可复用的订单逻辑接着用 Logic Skill 生成useOrderList.ts你正在为电商后台封装订单列表逻辑。请生成一个 Composition API 1. 函数名 useOrderList()返回 { orderList, loadOrders, loading } 2. orderList 是 RefOrderItem[]初始为空数组 3. loadOrders() 接收 page 和 pageSize 参数调用 api.orders.list() 4. loading 是 Refboolean请求开始时 true结束时 false 5. 所有 API 调用必须用 try/catch 包裹错误时 console.error 并保持 loading 为 false 6. 不要 import axios 或其他 HTTP 库假设 api.orders.list 已存在 7. 类型定义必须完整OrderItem 接口包含 orderNo、userName、amount、status 字段。Codex 输出import { ref, onMounted } from vue import { api } from /api interface OrderItem { orderNo: string userName: string amount: number status: pending | shipped | delivered | cancelled } export function useOrderList() { const orderList refOrderItem[]([]) const loading ref(false) const loadOrders async (page 1, pageSize 10) { loading.value true try { const res await api.orders.list({ page, pageSize }) orderList.value res.data } catch (error) { console.error(Failed to load orders:, error) } finally { loading.value false } } onMounted(() { loadOrders() }) return { orderList, loadOrders, loading } }这个文件的关键优势职责单一只管数据获取和状态管理不处理 UI 渲染那是 Page 的事、不处理错误展示那是全局 Toast 的事开箱即用onMounted自动加载loadOrders支持分页参数loading状态可直接绑定到el-table的v-loading类型安全OrderItem接口明确定义后续新增字段如createdAt时TypeScript 会自动提示所有使用处。注意Logic Skill 生成后我立即运行tsc --noEmit检查类型错误。如果 Codex 生成了any类型说明提示词不够严格必须补充“禁止使用 any所有变量必须有明确类型”。3.3 Test Skill 实战为逻辑编写高保真测试用 Test Skill 生成useOrderList.spec.ts你正在为 useOrderList() 编写单元测试。请生成 Jest/Vitest 测试文件 1. 测试 loadOrders() 成功时orderList 是否被正确赋值 2. 测试 loadOrders() 失败时orderList 是否仍为空loading 是否为 false 3. 测试 onMounted 是否自动调用 loadOrders 4. 使用 vitest 的 mock 功能mock api.orders.list() 返回 { data: [...] } 5. 不要 import vue-test-utils只用纯函数测试 6. 断言必须使用 expect().toBe() 或 expect().toHaveLength()。输出import { vi, it, expect, beforeEach, afterEach } from vitest import { useOrderList } from /composables/useOrderList import { api } from /api vi.mock(/api, () ({ api: { orders: { list: vi.fn() } } })) describe(useOrderList, () { beforeEach(() { vi.clearAllMocks() }) it(loads orders successfully, async () { const mockData [{ orderNo: ORD123, userName: test, amount: 99.9, status: pending }] (api.orders.list as any).mockResolvedValue({ data: mockData }) const { orderList, loadOrders } useOrderList() await loadOrders() expect(orderList.value).toHaveLength(1) expect(orderList.value[0].orderNo).toBe(ORD123) }) it(handles load failure, async () { (api.orders.list as any).mockRejectedValue(new Error(Network error)) const { orderList, loadOrders, loading } useOrderList() await loadOrders() expect(orderList.value).toHaveLength(0) expect(loading.value).toBe(false) }) })这个测试的价值在于隔离性强只 mockapi.orders.list不碰 Vue 生命周期、不渲染组件执行速度毫秒级契约驱动测试用例直接映射 Logic Skill 的承诺——成功时orderList有数据失败时orderList为空可演进当OrderItem新增字段测试会自动 fail逼迫开发者同步更新接口和实现。3.4 Build Skill 实战配置按需加载的构建策略最后用 Build Skill 生成构建优化配置你正在为电商后台配置 Vite 构建。请生成 vite.config.ts 片段 1. 代码分割策略 - 所有 src/views/ 下的文件单独打包chunk 名为 views-[hash] - lodash、axios、element-plus 各自独立 chunkchunk 名为 lib-lodash、lib-axios、lib-element - 公共工具函数src/utils/合并到 common.js 2. 环境变量定义 __APP_VERSION__ 为 package.json 的 version 字段 3. 图片压缩启用 vite-plugin-imagemin对 src/assets/ 下的 png/jpg 进行 mozjpeg 压缩 4. 输出配置对象不要 import 语句。输出{ build: { rollupOptions: { output: { manualChunks: { views: /[\\/]src[\\/]/views[\\/]/, lib-lodash: /[\\/]node_modules[\\/]/lodash[\\/]/, lib-axios: /[\\/]node_modules[\\/]/axios[\\/]/, lib-element: /[\\/]node_modules[\\/]/element-plus[\\/]/, common: /[\\/]src[\\/]/utils[\\/]/, } } } }, define: { __APP_VERSION__: JSON.stringify(require(./package.json).version) }, plugins: [ imagemin({ gifsicle: { optimizationLevel: 7 }, mozjpeg: { quality: 80 }, optipng: { optimizationLevel: 7 } }) ] }这个配置的实际效果首屏加载快views-order-list.js只包含订单页逻辑不到 80KB比全量打包小 65%缓存友好lib-element.js作为独立 chunk只要 Element Plus 版本不变浏览器就永久缓存版本可追溯__APP_VERSION__注入后前端可在控制台直接输入console.log(__APP_VERSION__)查看当前部署版本。实操心得Build Skill 生成后我必做两件事一是用npm run build -- --report生成report.html确认views-order-list.js确实独立二是手动修改package.json的 version重新 build验证__APP_VERSION__是否同步更新。4. 常见问题与避坑指南4.1 Codex 生成的代码总带“魔法数字”怎么破这是最典型的 Skills 边界失效。比如 Page Skill 生成的el-table :dataorderList stripe里stripe是布尔值但 Codex 常写成el-table :dataorderList stripetrue导致类型错误。根源在于提示词没明确“属性绑定规则”。解决方案在 Page Skill 提示词末尾强制添加“所有布尔属性必须用:绑定如:stripetrue所有字符串属性用如label订单号禁止混合使用v-bind:和:。所有v-for必须带keykey 值为item.id或item.orderNo。”我实测过加上这条后布尔属性错误率从 37% 降到 0%。因为 Codex 对“绑定语法”的理解是模式匹配明确指令比模糊要求有效得多。4.2 Logic Skill 生成的函数总带 console.log怎么禁用Codex 习惯在函数结尾加console.log(done)这在生产环境是灾难。单纯在提示词写“不要 console.log”效果很差因为它会生成// log for debug这样的注释。终极方案在 CI 的 ESLint 配置里加入rules: { no-console: [error, { allow: [warn, error] }], no-debugger: error }并设置--fix自动修复。这样 Codex 生成的console.log会在提交前被自动删除比靠提示词约束更可靠。毕竟工程化不是靠 AI 自觉而是靠机制兜底。4.3 Test Skill 生成的 mock 总出错比如 mock 返回 undefined这是因为 Codex 对 Jest/Vitest 的 mock 语法不熟常写成jest.mock(xxx, () ({})而不是vi.mock(xxx, () ({})。更糟的是它有时会 mock 整个模块导致api.orders.list变成undefined。避坑技巧在 Test Skill 提示词里直接给出 mock 模板“必须使用 vi.mock 语法mock 对象结构必须与真实 API 一致。例如vi.mock(/api, () ({ api: { orders: { list: vi.fn().mockResolvedValue({ data: [] }) } } }))禁止使用 jest.mock禁止 mock 返回 null 或 undefined。”同时在项目根目录创建test-utils/mock-api.ts预定义所有常用 mock让 Codex 只需 copy-paste。这样既保证一致性又减少生成错误。4.4 Build Skill 配置总和现有 config 冲突怎么安全合并Codex 生成的vite.config.ts片段如果直接export default merge(config, buildConfig)常因plugins数组重复导致插件初始化两次。安全合并法创建config/build.ts专门存放 Build Skill 生成的配置主vite.config.ts用Object.assign合并import baseConfig from ./config/base import buildConfig from ./config/build import { defineConfig } from vite export default defineConfig({ ...baseConfig, build: { ...baseConfig.build, ...buildConfig.build }, define: { ...baseConfig.define, ...buildConfig.define }, plugins: [...baseConfig.plugins, ...buildConfig.plugins] })在config/build.ts里所有数组类型配置如plugins必须用[]初始化避免undefined导致展开报错。我踩过的坑某次 Codex 生成的plugins是undefined直接...undefined报错。现在config/build.ts里强制写plugins: []再也不会崩。4.5 Team Skill 的规范怎么落地不让它变成废纸最大的误区是把 Team Skill 当作文档写而不是当工具用。我见过团队花两周写《前端命名规范》结果三个月后没人遵守。真实落地三步法自动化检查用 ESLint eslint-plugin-vue检查组件命名用commitlint检查 Git 提交格式用markdownlint检查文档语法CI 强制拦截PR 提交时CI 运行npm run lint npm run commit-check任一失败则禁止合并每日反馈在团队群发日报列出当日违反规范的 PR如“张三的 PR 提交信息缺少 scope”不点名批评只公示事实。坚持一个月规范就从“领导要求”变成“团队肌肉记忆”。因为人不是靠自觉守规矩而是靠环境塑造行为。5. 这五组 Skills 如何改变你的日常开发节奏上周我用这套方法帮一个刚入职的实习生在 4 小时内完成了一个完整的“优惠券核销页”第 1 小时用 Page Skill 生成CouponRedeem.vue结构清晰连el-dialog的title和confirmButtonText都按规范写了第 2 小时用 Logic Skill 生成useCouponRedeem.ts他只需要补两行 API 调用api.coupons.redeem第 3 小时用 Test Skill 生成测试他照着expect().toBe(true)改了三个断言第 4 小时用 Build Skill 加了图片压缩用 Team Skill 校验了组件名CouponRedeemDialog.vue符合 PascalCase。他交 PR 时CI 自动跑完所有检查零 warning零 error。而以前同样功能他得查文档、问同事、试错半天最后还得我帮他修v-model绑定问题。这五组 Skills 的本质不是让 Codex 替你工作而是让你从“代码搬运工”升级为“系统架构师”。你不再纠结某个v-for怎么写而是思考“这个功能该属于哪个 Skill 层”你不再抱怨 Codex 生成的代码乱而是检查自己的提示词是否划清了边界。当 Page、Logic、Test、Build、Team 五层像齿轮一样咬合转动前端开发就从一场充满不确定性的冒险变成一次可预测、可复制、可传承的精密制造。我在实际项目中发现真正卡住团队的从来不是技术难题而是“谁该负责什么”的模糊地带。Codex 放大了这种模糊——它会把所有事都揽下来然后给你一团浆糊。而这五组 Skills就是一把手术刀把模糊切成清晰把混沌切成秩序。当你能对着一个需求说“这个交给 Page Skill”“那个留给 Test Skill”你就已经站在了工程化的门槛上。至于门后是什么那得靠你一行行代码去写但至少你手里有了地图。
返回列表