最近我几乎每天都在用Codex这类AI编程助手写前后端代码。起初我也只当它是个能聊天的搜索框,问一句“帮我写个用户列表页”,它交出来的东西确实能跑,但跟我的项目风格、数据字段、交互逻辑总是差着一截,改起来比手写还累。真正转机是我把提示词当成一门手艺来打磨之后——同样的工具,同样的技术栈,产出质量和效率能差出好几倍。
这篇文章打算把这些实践整理一遍:从提示词的底层结构讲起,到前端组件、后端接口、前后端联调的具体配方,再到我踩坑之后总结的代码审查清单。内容会尽量给可复制的提示词模板和完整示例,适合刚开始接触AI编程助手的前后端工程师,也适合想在项目里把这套工作流跑起来的小团队和独立开发者。
1. 为什么前后端开发要重新学习“提问”这门手艺
1.1 搜索式提问和协作式提问的差别
很多新人容易把AI编程助手当成搜索引擎用。搜索引擎的任务是帮你“找到信息”,你输入关键词得到的是链接列表;AI编程助手的任务则是帮你“生成交付物”,你输入的是需求、约束和背景,它返回的是代码、方案或解释。这个底层差异决定了提问方式完全不一样。
搜索引擎可以容忍模糊,AI编程助手则非常吃“确定性”。你说“写个登录页”,它可以给一百种写法,每种都合理,但大概率不是你项目里想要的那种。这就像你让一位实习同事“把登录页做一下”,对方不问你用的什么框架、接口返回什么字段、要不要验证码、风格走什么路线,直接咔咔一顿写,你拿到手肯定要返工。AI编程助手也是这个状态,而且它没有读心术,唯一的协作通道就是提示词。
我在实测里的体会是,花在提示词上的时间不是成本,而是投资。同样一个组件,写清楚上下文和随手三分钟一句话,AI交付的质量差距能到两到三倍。很多团队试过AI之后觉得“不过如此”,多半不是工具不行,而是提问方式还停留在搜索时代。
1.2 前后端对提示词的需求天然不同
前端开发的交付物是界面和交互,提示词里侧重的是组件结构、视觉风格、状态流转、响应式行为;后端开发的交付物是接口和数据逻辑,提示词里侧重的是数据模型、协议规范、异常分支、性能边界。一套提示词不可能同时覆盖两个方向。
举两个极端例子。前端适合的提示词通常长这样:“按设计稿实现顶部导航和侧边栏,菜单数据走接口,收起时保留图标模式”;后端适合的提示词则是:“为订单模块设计查询接口,支持分页、按状态筛选、返回统一响应结构”。如果把这两段要求混在一起发给AI,它往往会在中间地带做妥协,前端代码带着后端思维,后端代码又掺着页面逻辑。
所以我在实际项目中会维护两套提示词骨架,前端一套,后端一套,联调时再补一套契约层。后文我会分别拆开讲,每一套都有可以直接复制的模板。
2. 让Codex听懂人话:提示词的底层结构与黄金要素
2.1 五要素:角色、上下文、任务、约束、输出格式
我打磨了很多轮之后,总结出提示词的五个核心要素:角色、上下文、任务、约束、输出格式。五要素不一定每次全部出现,但一旦任务稍微复杂,最好一个都别省。
| 要素 | 作用 | 参考写法 | | 角色 | 限定AI的身份视角与专业水平 | “你是一名精通TypeScript的资深前端工程师” | | 上下文 | 提供技术栈、业务背景、已有代码 | “项目技术栈为React 18 + TypeScript,已有请求封装位于src/api” | | 任务 | 明确本次要交付的东西 | “实现一个带搜索和筛选的商品列表页” | | 约束 | 说明不许做什么、必须怎么做 | “禁止使用any;样式统一用CSS变量;依赖只用已有包” | | 输出格式 | 规定交付形态,便于直接接入 | “输出TSX组件代码,并在代码上方用注释说明Props类型” |
角色这个要素容易被忽略,实际很关键。让AI以“资深工程师”身份作答,它的输出会默认带上工程化习惯,比如类型定义、错误处理、可维护性说明;不给角色时,它偏向“尽力完成最小需求”,常常只给出能跑通的代码。上下文是五要素里最花时间的,也最值得花时间——AI的产出质量,很大程度由上下文决定。
2.2 坏提示词和好提示词的差距
先说反面例子。我曾经直接问过这样一句话:“帮我写一个用户列表页面。”Codex返回了一个通用表格,包含用户名和邮箱两列,用了一个我项目里根本没装的UI库,分页逻辑还是自带假数据。问题很明显:框架未知、字段未知、交互未知、样式未知,它只能用最通用的预设来填。
同一需求,我会改写成这样(这段可以直接复制改造):
你是一名资深前端工程师,精通React 18和TypeScript。 项目背景:一个后台管理系统,使用Vite构建,UI库是Ant Design 5,已有请求函数 request 封装在 src/api/request.ts。 任务:实现一个用户列表页面 UserList,展示字段为用户ID、姓名、角色、状态、创建时间。 交互要求: 1. 支持关键字搜索用户姓名; 2. 支持按角色和状态筛选; 3. 分页从0开始,每页10条。 约束: 1. 所有接口字段类型显式声明,禁止使用 any; 2. 不要引入新的依赖; 3. 加载和空状态都要处理。 输出:完整的 TSX 代码,并在文件顶部用注释说明组件对外暴露的 Props。这一条提示词复制到模型里,产出的组件基本可以直接放进页面,改的往往只是个别字段名。核心原因是它提供了足够的“决策前提”,AI不需要替你猜了。
2.3 上下文适量原则:信息太多反而引出幻觉
有一次我在提示词里贴了整整一个文件,几百行,想让AI基于它补一个新函数,结果它把无关的地方也顺带改了,还引入了一个不存在的工具方法。复盘下来,是上下文太多导致注意力被稀释,模型分不清重点。
我的经验是上下文“精而不多”。贴现有代码时只贴关键片段:组件的props定义、请求函数的返回类型、样式变量文件里的几个变量名;描述交互时用一两句话交代清楚事件链路。如果项目里确实有长文件要参考,可以复制文件头部类型定义部分,而不是全量塞进去。
还有一个实用技巧:一次只问一件事。同时让AI“加一个导出按钮,顺便把搜索逻辑重构了,再补一下空状态”这种提示词,看起来省事,实际它会在多个目标之间找平衡,结果每个目标都做得很平庸。拆分提问,每轮聚焦一个交付物,反而总耗时更短。
3. 前端场景实战:从组件生成到样式联调的提示词配方
3.1 组件生成配方:把接口字段写死,风格再放权
前端组件是最适合用AI提效的场景,因为组件本质上是“结构加状态的确定性输出”。只要你把字段列表、交互节点和数据源说清楚,AI生成骨架的速度非常快。我在2.2节给的示例就是组件生成的通用配方,这里再补三条经验。
第一条,字段清单要像接口文档一样写。列表展示什么、表单提交什么,逐项列清楚,AI生成的表格列、表单校验才不会缺漏。第二条,状态归属要说清。这个状态是组件内部管理,还是由父组件通过props控制,直接决定了生成代码的结构。第三条,如果项目有设计系统,一定要在提示词里点名,比如“按钮统一使用Ant Design的Button,圆角用项目里的--radius-md变量”,否则AI很容易写出一堆内联样式。
3.2 样式与响应式:用约束对抗“能跑就行”
AI生成的前端代码最常被吐槽的就是样式粗糙。根本原因是视觉审美很难靠模糊语言传达,但可以用“约束加参考”的方式锁定范围。你需要告诉它间距体系、色彩来源、断点规则,要是项目里有现成的CSS变量,直接把变量名和用途写进提示词。
比如生成一个响应式商品卡片时,可以这样补充样式约束:
样式规则: - 字体、间距、圆角统一使用项目已有的CSS变量,禁止写死px; - 卡片在768px以下显示单列,768到1200px显示两列,1200px以上显示四列; - 图片使用 aspect-ratio 1:1,防止加载时布局跳动; - hover时卡片阴影加深,过渡时间0.2s。加上这些约束之后,AI产出的样式质量会明显提升,返工次数大幅降低。不要指望AI自己“悟”出设计系统,它没法看到你的设计稿,只能靠你把规则喂给它。
3.3 前端Debug的正确姿势:报错全文加操作路径
用AI修bug,最容易翻车的写法是:“我的页面白屏了,帮我看看。”它没有报错、没有代码、没有复现步骤,只能给你一堆通用排查建议。正确姿势是把调试信息按四段填满:
报错信息:<粘贴浏览器控制台完整报错> 相关代码:<粘贴出问题组件的核心代码段,而不是整个文件> 操作路径:进入页面 -> 点击筛选 -> 选择价格区间 -> 控制台报错 期望行为:点击筛选后列表按条件刷新,不应报错 实际行为:列表清空,控制台出现 Cannot read properties of undefined这样模型能很快定位到问题大概率出在筛选参数结构或列表数据初始化上。我自己用这套流程调过几十个bug,命中率比“直接贴报错”高出一大半。还有个小技巧:把网络请求的Payload和响应一起贴进去,很多前端问题其实是字段名对不上。
4. 后端场景实战:接口设计、数据模型与异常处理的提示词策略
4.1 从一句业务描述到数据模型:概念先行
后端开发里,数据模型是所有代码的地基,AI在这块的发挥很稳,前提是你把业务概念说清楚。有一次我需要为一个订单模块建表,第一版提示词只写了“订单表需要包含用户、商品、金额和状态”,结果它建了一张扁平表,把商品信息直接塞进订单表,完全没考虑多商品订单。问题出在业务规则没给够。
改成这样之后,产出的结构就对了:
你是一名资深后端工程师,负责一个电商项目的数据库设计。 业务规则: 1. 一个订单可以包含多个商品,商品快照需要独立存储,因为商品会改价; 2. 订单有状态流转:待支付、已支付、已发货、已完成、已取消; 3. 金额统一用分为单位存储,避免浮点误差; 4. 用户可能批量查询订单,需要在 user_id 和 status 上建立索引。 任务:设计订单模块的MySQL表结构,包含订单表、订单商品表、必要的枚举字段说明。 输出:建表SQL,外加每个字段的注释和索引说明。这样AI生成的表结构既有订单主表又有订单明细表,金额字段用了分,还在关键查询字段上加了索引。很多人说AI不懂业务,其实是提示词里没有提供业务规则。业务规则多少,AI的设计能力就有多少。
4.2 接口骨架:先谈协议,再谈实现
我习惯让AI先输出一份接口协议清单,把路径、方法、参数、响应结构列清楚,确认无误后再让它生成Controller和Service代码。这一步能避免大量无效代码——如果协议错了,实现的代码写得再漂亮也要推倒重来。
协议生成的提示词模板:
基于以下数据模型,设计订单模块的REST接口: - 数据模型:<粘贴上一步生成的表结构或实体定义> - 需要的能力:创建订单、支付回调、订单列表查询、订单详情、取消订单 约束: 1. 路径命名遵循 REST 风格,资源名使用复数; 2. 查询接口必须支持分页参数 page/pageSize,排序参数 sort; 3. 统一响应结构为 { code, message, data }; 4. 不要把内部实体直接暴露给前端,提供对应的DTO。 输出:一张接口表格,列包含方法、路径、入参、出参、错误码。拿到这张协议表,我再复制给AI生成具体代码,每一层的职责会被分得很清楚。实测下来,经过协议步骤的生成代码,整体返工率比直接跳到实现低很多,因为人的确认点从代码逻辑前移到了设计层面,检查成本也低。
4.3 并发、幂等和异常:这些字段别让AI猜
后端最容易翻车的场景是并发和边界。AI生成的接口代码如果没人提醒,多半对并发处理是空白的。我在提示词里最后固定会加一段“异常与边界要求”:
异常与边界要求: 1. 创建订单接口必须支持幂等,调用方传入 idempotencyKey,重复请求返回首次结果; 2. 扣减库存需要保证原子性,防止超卖; 3. 所有外部服务调用必须设置超时时间,并在超时后返回明确错误码; 4. 参数校验使用统一工具,非法参数返回 400 和具体字段错误信息。把这些要求写进提示词,AI生成的代码会自动补上分布式锁、唯一索引、超时保护这类手段,否则它就只会写CRUD。后端提示词的价值不在于代替架构师,而在于把架构师定的规则批量落实到每个接口上。
5. 前后端联动:用一套提示词体系打通全栈开发链路
5.1 接口契约先行:让AI先产出OpenAPI文档,再各干各的
我目前最顺的全栈工作流,是让AI先生成一份OpenAPI风格的接口文档,然后再让它分别基于这份文档生成前端类型定义和后端接口实现。这个思路等于把“契约测试”提前到了开发之前。
具体操作是这样:先把整体业务需求写成一长段提示词,让Codex输出一份完整的接口定义,包含所有路径、参数、DTO字段。然后,前端提示词里加一句“以下接口定义为本项目唯一数据来源”,粘贴接口定义;后端提示词里也加同样一句,粘贴同一份定义。两边看到的字段语义完全相同,字段命名、嵌套结构、参数名自然就对上了。
这样做最直观的好处是,联调阶段以前常见的“前端传 userId 后端要 user_id”“后端返回 created_at 前端读 createTime”这类问题几乎绝迹。字段冲突从代码编写期就被消灭了。
5.2 需求描述作为单一事实来源
很多项目的前后端需求描述其实是分开写的,前端看到的是页面交互文案,后端看到的是业务逻辑文档,两边对业务的理解天然存在偏差。我现在的做法是:把最核心的业务需求抽取成一段“中性描述”,不区分前端后端,同一段文字同时喂给两边。
例如用户积分系统的核心描述:
业务规则:用户完成订单后获得积分,积分值等于订单实付金额向下取整;积分可以用于抵扣订单金额,1积分抵扣0.01元;积分变更需要记录流水,流水不可删除。前端拿着这段描述生成积分页、积分流水列表、抵扣入口;后端拿着同一段描述生成积分账户表、流水表、变更接口。两边从同一事实出发,页面展示的数据和后端返回的数据天然一致,后续需求变更也只需要改这一处描述再重新生成。
5.3 用提示词一键生成Mock数据
联调等不到后端接口是家常便饭。我现在用Codex生成Mock数据很顺手,只要给出DTO定义,剩下交给AI。比如:
根据以下字段定义生成20条Mock数据: - id: number,自增 - userName: string,中文姓名 - role: 'admin' | 'editor' | 'viewer' - status: 1 | 0 - createdAt: ISO时间字符串 要求:数据尽量随机但合理,角色分布均匀,输出JSON数组。生成的Mock数据比手写真实得多,关键是字段结构一定和契约一致,因为契约就贴在提示词里。前端联调时表格、筛选、分页全部跑得有模有样。
6. 实测中的意外与优化:AI生成代码的审核清单
6.1 翻车现场复盘:AI不是不会错,是错得很有创意
用久了你会发现,AI生成代码的错误通常不是语法错误,而是语义层面的偏差。我遇到最典型的有几类。
第一类,AI自作主张。让它生成订单列表,它顺手加了个“导出Excel”功能,还引入了一个date处理库。解决方式很直接:约束里明确“只实现列出的功能,不要添加额外能力”。第二类,版本幻觉。项目用的React 18,它写了React 19才支持的新API;用的Spring Boot 2.x,它生成了3.x配置。解决方式是上下文里把版本号写死,最好是连脚手架版本也贴进去。第三类,依赖不存在。它编造了一个听上去很合理的第三方包名,安装时直接失败。解决方式是在约束里加一句“所有依赖必须是真实存在且已在package.json中列出的包,如果无法确认请明确告知”。
6.2 我把合并AI代码前的六道检查写成了清单
每次准备把AI生成的代码合并进项目,我都会过一遍下面这六项,没通过就先不合并:
- 安全红线:有没有SQL拼接、危险HTML注入、敏感信息硬编码;
- 类型闭环:从接口请求到页面渲染,类型是否全程可追溯,有没有偷懒的any;
- 边界覆盖:空数据、极端值、超长文本、网络超时有没有处理;
- 错误路径:失败时用户能看到什么,后端有没有返回明确错误码;
- 依赖真实性:新增依赖是否确有此包、版本是否与项目兼容;
- 性能反模式:有没有N+1查询、重复渲染大列表、缺少分页等。
这份清单不区分前端还是后端,两个方向都适用。用AI开发提速的前提是审核跟上,否则代码合并得越快,技术债积累得越快。
6.3 多轮迭代提问:一次生成不满意?追问比重写更省力
我见过不少人在AI给出一版代码后,觉得不满意就重新生成一次,来回了好几次还是不满意。其实更好的方式是在同一轮对话里做“迭代追问”。
比如AI生成的组件用了useEffect来初始化数据,你希望改成事件触发,不用推翻重来,直接追一句:“这里不要使用useEffect,把数据加载移到用户点击搜索按钮时触发,其他逻辑保留。”又比如它生成的布局在窄屏下崩了,你可以追问:“给筛选区域在768px以下增加折叠,保持原有逻辑不变,只输出需要修改的代码片段和改动位置。”这种迭代式的追问,既保留了前一轮的正确部分,又只针对缺陷做局部修正,效率和稳定性都远高于反复重新生成。
最后分享一个习惯:我会把高频提示词模板整理成一份团队共享文档,字段、约束、输出格式都做成可填空的形式。新成员接手项目,拿模板改几十个字段就能开工,不再需要从零摸索。用AI做开发从来不是玄学,本质就是把需求翻译成机器能执行的准确指令,前期多花三分钟组织提示词,后期往往能省下几小时的改代码时间,这个账怎么算都划算。