
干前端这些年我最怕的一个词不是需求变更而是 Mock。你可能要说Mock 不是提升开发效率的好东西吗前期确实好用但走到联调那天你就明白了——前端页面里密密麻麻的属性和后端真正返回的 JSON 对不上号十个组件九个在改数据字段。后来我换了个思路既然前后端打架的本质是“接口契约不一致”那我就直接用 AI 去扫后端代码把真实契约提取出来再生成一套能直接对接真实接口的前端。这篇文章就是这套方案的完整复盘包括我的思考过程、实际 Prompt、踩过的坑和最后的适用边界判断。如果你正被联调折磨或者想搞清楚 AI 编程到底能帮前端到什么程度这篇应该值得你读完。1. 为什么 Mock 是前端开发里最大的“温柔陷阱”1.1 Mock 数据的三宗罪先说清楚我不是要一棒子打死 Mock。原型设计阶段、后端还没动工时Mock 几乎不可避免。但很多团队把 Mock 用成了“默认开发模式”前端在 Mock 后面躲了半个月等联调那天一次性爆炸。第一宗罪是字段不同步。后端接口文档写的是user_idMock 里我拍脑袋写了userId。你以为这只是命名问题列表页的 key、详情页的回显、提交时的参数映射全都跟着这个字段串一遍。我一个 300 行的组件为了一个字段名改动连带改了十几个引用位置Review 花了二十分钟最后发现后端其实两个字段都返回了自己白折腾。第二宗罪是类型失真。Mock 里分页永远返回list真实后端返回的是recordsMock 里接口永远有数据真实接口空数据时返回nullMock 里金额是 number真实后端为了防止精度问题返回的是 string。这些问题不到真实联调根本暴露不出来等暴露的时候前端组件已经按错误的类型写完了。第三宗罪是鉴权和边界被判了“无期徒刑”。Mock 数据不经过登录态、不触发 403、不校验上传大小限制前端代码看起来跑得飞快实际上健壮性约等于零。很多前端开发的隐患都是这么攒出来的只在 Mock 环境里演示过从来没见过真实异常。1.2 这个项目的核心思路让后端代码当“唯一真相”所以我把方案整体反转了一下不再让 AI 凭空生成前端页面而是让 AI 先去读后端代码输出一份接口契约再基于这份契约去生成前端。这里的“契约”是关键词它包含了接口路径、请求方法、参数结构、响应字段、类型和状态码约定。后端代码在这里扮演的是“单一事实来源”Single Source of Truth。AI 会扫描 Controller、路由定义、DTO、实体类、校验注解、统一响应包装类甚至配置文件里的 context-path然后输出一份结构化的 OpenAPI 描述再转成前端的 TypeScript 类型和请求层。这个顺序非常关键。如果你直接跟 AI 说“帮我写一个用户列表页面”AI 大概率会自己编一套字段生成出来的东西还是等于 Mock只不过包装得更精致。但如果让 AI 先从后端代码里“复述”出接口长什么样生成代码就变成了按图纸施工而不是凭想象盖楼。1.3 与传统工作流的对比对比一下三种前端对接后端的方式你能更清楚看到差异工作流契约来源主要问题传统 Mock 开发前端凭接口文档或个人想象字段、类型、状态码大概率不一致联调返工后端先写 OpenAPI再生成前端手工维护的 OpenAPI 文档文档维护成本高经常滞后于代码扫描后端代码生成契约本项目后端源码实时推导首次 Prompt 设计有门槛复杂项目需要人工校验我用下来的体感是第三种方案最大的价值不在“自动化生成页面”而在于它把前后端之间的信息损耗压到了最低。后端代码改了重新扫描一遍前端契约跟着更新那种“文档说一套、代码跑另一套”的经典矛盾基本被干掉了。2. 工具选型与扫描策略给 AI 喂什么它就吐什么2.1 工具链怎么组合先交代一下我用的工具不一定是最优解但实测下来踩坑少。核心需要一个支持多文件上下文、能查看整个项目目录结构的 AI Agent 类工具。我日常用的是 Claude Code 和 Cursor 换着来GitHub Copilot 虽然方便但做这种跨文件的“代码考古”工作上下文窗口和主动探索能力弱了一些。如果你想用国产工具通义灵码这类支持仓库级上下文的也可以思路是通用的。辅助工具方面后端代码得能在本地打开方便 AI 读取整个目录树。最好后端环境里有 Swagger 或 OpenAPI 的生成依赖有的话 AI 扫描效率会翻倍没有也没关系直接读源码也能提取。最后准备一个接口调试工具我自己习惯用 ApifoxPostman 也行但后面联调阶段我更多用浏览器 F12 直接看 Network。2.2 扫描范围什么该扫什么坚决不扫让 AI 扫后端代码最忌讳的就是把整个仓库一股脑丢进去。后端代码里充满了 Service 实现、Mapper、定时任务、内部 RPC 调用这些不仅浪费上下文还会严重干扰 AI 对“外部 HTTP 接口”的判断。我在实践里总结了一个优先级清单需要扫描的路由定义层Controller、路由注册函数、装饰器、请求和响应模型DTO、VO、BO、Entity、统一返回包装类、业务状态码常量、鉴权相关中间件、配置文件里的 context-path 和端口。不需要扫描的Service 内部实现、数据库查询逻辑、定时任务、FeignClient 内部的远程调用接口、消息队列消费逻辑。实际操作中我先让 AI 看一眼项目目录结构自己判断哪些目录是 Controller 层。再给它一个“排除清单”比如出现FeignClient、DubboService的类直接忽略。这一步看似简单能避免后续生成一堆“假前端接口”——我最初没做排除的时候AI 把十几个内部服务间调用接口也生成了页面浪费了小半天。2.3 提示词把 AI 变成“契约提取器”的完整模板我试过很多 Prompt 写法最稳的是下面这个框架。核心是三条限定范围、明确输出格式、禁止猜测。你是一个后端代码分析专家。请阅读这个项目的 Controller、DTO、VO 和实体类目录只关注对前端暴露的 HTTP 接口忽略 Service、Mapper、FeignClient、定时任务等内部实现。 输出一份 OpenAPI 3.0 格式的 JSON 契约文件 1. 每个接口包含 method、path、请求参数query/body/path 三种类型、参数类型 2. 每个响应包含状态码、响应体字段名、字段类型、是否必填、嵌套结构的对象映射 3. 特别注意统一响应包装层、分页结构、文件上传接口和鉴权要求 4. 对不确定的字段不要猜测标记为 TODO 并说明不确定的原因 5. 每次先输出你找到的接口清单确认后我再让你输出完整 JSON这个 Prompt 和我一开始随手写的“请帮我分析后端代码”最大的区别在于它给 AI 设定了明确的行为边界。尤其是第 4 条“不确定就标 TODO”直接把 AI 的“脑补”本能关掉了。AI 生成代码时最喜欢把缺失信息自动补全但在契约提取这种场景里补全就是灾难源头。另外一个小技巧让 AI 分模块批处理。如果一个后端项目有用户、订单、商品三个模块别让 AI 一次扫完那会导致上下文溢出后半段接口开始偷懒简化。我通常让 AI 先扫用户模块输出校验通过后再扫订单模块最后合并成一份总契约。3. 核心实操从后端契约到可运行前端的全流程3.1 第一步生成并校验 OpenAPI 契约拿到后端代码后我先把 Controller 层、DTO 目录、统一返回类和 application.yml 路径告诉 AI让它按上一节的 Prompt 输出 openapi.json。第一次生成的 JSON 大概率会有格式小问题没人能一次写对我会用npx apidevtools/swagger-cli validate openapi.json这类工具做语法校验没有工具就让 AI 对照 OpenAPI 规范自检两遍。校验通过不代表内容是对的。我还会抽查两三个关键接口比如带分页的列表接口和带嵌套对象的详情接口去后端代码里手动确认路径和字段。这一步相当于给 AI 的输出做代码 Review花的时间很少但能过滤掉后续生成前端时的连带错误。3.2 第二步把契约转成 TypeScript 类型openapi.json 不是前端能直接用的东西需要转成 TypeScript 类型定义。这个过程完全可以交给 AI但你要给它定规则否则它生成的类型会“图省事”// 预期生成的简化示例 export interface UserVO { userId: string // 后端 Long 类型序列化为 string防止精度丢失 nickName: string | null // 后端 Optional 字段允许为空 status: ACTIVE | DISABLED // 枚举转 union type createdAt: string // ISO 8601 时间字符串 }我实际给 AI 的转换规则包括后端枚举转 TS union type所有日期时间字段统一用 stringID 后缀字段手动确认是否要用 bigint 或 string后端下划线命名转前端驼峰命名。这里要强调一下命名转换不是简单的字符串替换而是要在请求层做一层“翻译”前端组件里永远用驼峰请求发出时再转回下划线。3.3 第三步封装请求层把鉴权和错误码统一干掉类型定义只是“静态层”真正让页面跑起来的是请求层。我会让 AI 基于契约生成一个统一的 client.ts功能包括设置 baseURL、自动携带 Token、统一解析后端返回包装、统一处理分页参数命名转换。// client.ts 核心逻辑示意 const http axios.create({ baseURL: /api }) http.interceptors.request.use(config { const token authStore.token if (token) config.headers.Authorization Bearer ${token} return config }) http.interceptors.response.use(res { const raw res.data if (raw.code ! 0) throw new Error(raw.message) return toCamelCase(raw.data) // 下划线转驼峰返回给页面的已经是干净数据 })这个请求层的意义是页面组件只需要关心业务数据不需要知道后端字段是user_id还是userId也不需要关心业务码是 0 还是 200。AI 很容易把请求层写散每个页面都自己去处理状态码和防抖。所以我在 Prompt 里会明确要求“所有接口必须走 client.ts不允许页面直接发请求”。3.4 第四步生成页面骨架契约和请求层就绪后生成页面就变得顺理成章了。列表页的表格列直接来源于列表接口的响应字段详情页的表单项直接来源于 DTO 字段提交页面的参数映射直接来源于 body 结构。AI 在这个阶段可以发挥它的模板能力快速搭出页面结构。我习惯让 AI 先生成“能用”的骨架而不是追求一次到位。具体说就是先保证数据能展示、表单能提交样式和交互后面再调。凡是让 AI 一步到位生成精美页面的尝试最后都会变成狗皮膏药式的修改。骨架生成后我只需要在真实接口跑通后再针对交互细节人工优化。3.5 第五步真实联调和 F12 里的“反向 Mock”前端跑起来后直接启动后端用真实数据过一遍主流程。我会打开浏览器 F12 的 Network 面板逐个接口核对路径有没有 404、请求参数是否匹配、响应字段是否和类型定义一致。这里有个听起来矛盾但非常必要的操作拒绝 Mock 不代表不能用调试工具伪造响应。真实接口验证通过后我会在 F12 控制台用 Fetch 拦截或者使用代理工具临时把某个接口的返回改成空数组、500 错误、超长字符串来测试前端页面的边界处理。这其实是“怎么在 F12 工具里 mock 接口返回参数”这个问题的正确用法——先保证真实接口没问题再故意造假数据测试前端健壮性而不是用假数据开发。4. 技术难点与类型推导避坑AI 生成时最容易翻车的 6 个细节4.1 不同后端语言到 TypeScript 的类型映射AI 扫描后端代码生成类型时最容易在类型映射上翻车。不同后端语言有自己的类型体系直接照搬翻译会出大问题。我整理了一份实测对照表后端类型前端 TS 类型注意事项Java Longstring 或 bigint雪花 ID、订单号超出 JS 安全整数范围必须转字符串Java BigDecimalstring金额精度问题不可用 numberJava LocalDateTimestring通常输出 ISO 8601需要自定义格式化Python Optional[str]string | null要保留嵌套在对象里的 null 可能性Go time.Timestring序列化格式不统一以接口实测为准Java 枚举union type如ACTIVE | DISABLED别写成 stringPHP mixed / Go interface{}unknown强迫 AI 标 TODO不要让它猜其中 Java Long 是最典型的坑。如果后端订单号是 Long前端用 number 接收一条超过 2^53 的订单号就会被静默截断看起来差几个数字实际上已经变成完全不同的 ID。AI 扫描源码时看不到这个运行时问题必须靠人对这种“后端类型系统与 JSON 序列化之间”的鸿沟有认知然后主动在 Prompt 里要求对 ID 后缀字段做 special 处理。4.2 Java 泛型擦除AI 为什么总把分页结果写成 any[]这是我在实操中翻车最惨的一次。后端代码里写的是PageUserVOAI 能看懂是用户分页但等到生成前端类型时它往往把records或list里的元素类型写成any[]。原因在于 Java 泛型在运行时会被擦除JSON 反序列化时如果不加额外配置根本不知道PageUserVO里的 T 是什么。遇到这种情况AI 自己很难解决需要你给它明确指令“当检测到 Page 、List 等泛型容器时必须从方法签名获取 T 的具体类型手动构造带类型的数组定义”。我后来会在 Prompt 里强制要求 AI 输出泛型推导的中间过程效果好了很多。4.3 布尔字段的 is 前缀陷阱Java 实体类里经常有private Boolean isDeletedLombok 生成的 getter 叫isDeleted()但某些 JSON 序列化框架会把字段名缩成deleted。AI 扫描源码时看到的是isDeleted生成的前端类型是isDeleted但真实接口返回的却是deleted页面永远拿到 undefined。这个坑几乎无法从静态代码分析绕过只能在联调阶段用 F12 看真实响应才能发现。我的处理方法是让 AI 生成类型时把这类布尔字段的预期 key 标记为“以接口实测为准”联调时单独过一遍布尔字段。4.4 文件上传和 FormData 的 Content-Type 问题AI 生成的请求层默认会把所有接口按 JSON 发送。遇到文件上传时如果你用 JSON 格式发二进制文件后端直接报错。生成文件上传接口时必须明确告诉 AI// 文件上传正确姿势 const formData new FormData() formData.append(file, file) http.post(/upload, formData) // 不要手动设置 Content-Type浏览器会自动带 boundary这类接口通常还涉及额外的 metadata 参数比如上传目录、文件名策略后端可能是 query 参数也可能是 formData 的一部分AI 容易漏掉。扫描时我会要求 AI 额外列出“所有带 MultipartFile 或文件流参数的方法并标注参数位置”。4.5 WebSocket 实时推送AI 只能看到握手接口后端有 WebSocket 服务时AI 扫描路由文件只能看到“连接握手”的端点服务端主动推送的消息结构在扫描阶段往往是缺失的。比如后端推送在线人数、告警消息时前端没有任何请求能触发响应接口契约自然提取不出来。我的办法是让 AI 去扫描后端 WebSocket 处理器的消息体模型类把这些模型单独生成 TS 类型并提供一个onMessage的类型守卫函数。类似 Django Channels 里定义的消息序列化器、Spring 里的 WebSocketMessage 子类都属于“虽然不在 HTTP 路由里但属于前端契约”的部分。4.6 统一响应包装嵌套层级AI 常把 data 这层弄丢国内后端项目几乎都有统一响应包装结构一般是{ code, message, data }。AI 扫描后容易把data里的内容当作顶层结构导致页面里拿到res.page实际上正确的路径是res.data.page。我在 Prompt 里会特别写明“如果存在统一的 Response 包装类在生成的类型定义中必须保留 wrapper 结构并在 client.ts 的响应拦截器里拆掉这一层后再返回给页面”。换句话说类型定义里要有包装层运行时数据不要带包装层。这个“类型层保留、运行时拆解”的设计能同时保证类型安全和页面使用的清爽。5. 常见问题与排查实录实测 6 个坑5.1 问题一接口路径全部多了一截前缀前端生成的接口是/users后端真实路径是/api/v1/users。最诡异的是这个前缀在后端代码里可能并不存在它是被网关或 Nginx 转发时加上的AI 排查无果。排查思路是让 AI 去看配置文件里的context-path以及部署配置里的网关路由规则。如果后端代码里确实没有前端 baseURL 里补上即可。这类问题是我在“前端传参”环节翻车率最高的推荐在生成 client 时就明确要求“读取 application.yml / settings.py 里的 context-path 并拼入 baseURL”。5.2 问题二AI 把内部服务接口也生成了页面现象是生成了一堆毫无前端意义的接口比如订单服务和库存服务之间的内部 RPC。原因是扫描时没有排除FeignClient、DubboService、gRPC 定义等。解决方法是扫描之前显式给 AI 排除清单。我后来在 Prompt 里加了一句“任何只在服务端内部使用的接口FeignClient、RPC、事件监听都必须跳过只保留能从浏览器直接访问的 HTTP 接口。”同时让 AI 在输出清单时标注每个接口的“判断依据”方便人工快速核查。5.3 问题三大数据精度丢失页面直接显示错订单号列表接口跑通后页面上的订单号最后几位变成了 0 或者乱码。这个就是 Java Long 序列化成 JSON 数字时溢出导致的。AI 无法通过静态扫描发现只有真实联调才会暴露。遇到这类字段最干净的解法是让后端把主键 ID、订单号等 Long 字段统一序列化为字符串。前端类型对应改为 string。如果后端改不了前端只能自定义 JSON 解析在拦截器里对特定字段做字符串化处理但这是补丁方案不推荐。5.4 问题四DELETE 接口有的带 body有的用 query后端团队历史原因导致风格不统一AI 生成请求层时只认准一种风格调某些接口时 404。排查方式是逐个看后端方法签名里 DELETE 方法是否有RequestBody。有就是 body 传参没有就是用 query 拼接。我在生成的 client 里会要求 AI 为每个接口独立标注“参数位置”避免一套 axios 配置强行适配所有接口。5.5 问题五字段名校验对不上表单永远提交失败页面表单校验通过后点击提交后端返回“参数错误”。通常是因为 AI 生成表单时字段名是驼峰后端却要求下划线或者字段类型不匹配。这套方案的解法已经很清楚了请求层统一做 camelCase 到 snake_case 的转换。我要求 AI 封装toSnakeCase函数在请求拦截器里自动转换这样一个页面代码里不需要有任何后端命名风格的痕迹。如果转换后还是失败就在 F12 看请求 payload和后端 DTO 字段一一对账。5.6 问题六校验规则缺失前端能提交但后端报错后端 DTO 上有NotNull、Size、Pattern这些注解AI 扫描时如果注意力都在字段类型上很容易漏掉这些校验规则。结果是前端表单没做任何限制用户能提交空值后端直接 400。我在 Prompt 里会单独要求“提取实体类或 DTO 上的校验注解转成前端表单校验规则包括必填、长度、正则格式。”Java Bean Validation 的注解和前端规则有天然的对应关系AI 完全能转只是它默认不主动干这事儿。5.7 问题排查速查表问题现象可能原因解决动作接口 404context-path 或网关前缀缺失读配置文件补 baseURL 前缀生成内部服务接口没有排除 RPC 定义Prompt 加排除清单订单号精度错误Long 溢出后端转字符串前端用 stringDELETE 接口报错参数位置用错逐个接口确认 body/query表单提交后端报参数错命名风格未转换请求层统一 snake_case 转换前端无校验后端报错校验注解被忽略要求 AI 提取校验规则6. 这套方案的适用边界与我的一点经验6.1 什么项目用这套方案最划算我体感最香的是“旧系统重构”场景。很多老后端跑了好几年接口文档早就不知道丢哪了Swagger 也没接入全靠看代码猜。这种时候让 AI 扫一遍后端代码直接生成契约和前端等于给老系统做了一次“接口考古”效率极高。其次是后端已经在开发中、前端需要同步起步的项目。以前我们靠 Mock 并行开发有了这套方案前端可以直接基于后端最新代码生成的契约开发虽然是并联推进但接口对齐的成本大幅下降。6.2 什么场景要谨慎后端代码质量极差的时候这套方案会放大问题。如果后端接口命名混乱、状态码随机、返回结构不统一AI 扫出来的契约本身就是混乱的前端生成得再漂亮也是豆腐渣上盖楼。这种情况我的建议是先把后端的关键接口结构理一遍至少保证列表、详情、提交三类核心接口有一个统一包装。还有就是强交互定制型页面。数据大屏的复杂布局、重交互设计、细腻的动画效果AI 生成不了也不应该强行让它生成。这套方案的定位是“骨架和基础设施的自动化而不是视觉和交互的替代者”。我生成页面骨架后交互和样式还是自己动手工作量已经从过去的三四天压缩到半天。6.3 顺着这个思路往后还能走这套方案最值得扩展的方向是 CI 化。后端每次提交后自动触发一次契约扫描将生成的类型定义同步到前端项目并提交 MR前后端联调可以在一个很短的反馈环里完成。实际我们已经尝试把 OpenAPI 产物作为内部 npm 包发布前端依赖的是后端代码实时推导出来的“活文档”不是手工维护的接口说明。我也想说一句相关的题外话。很多前端同行看到“AI 取代前端”的说法会焦虑但我的亲身体验是AI 首先要干掉的是那些繁琐、机械、重复的“接口搬运工”工作。Mock 数据对字段、改类型、写 CRUD 页面这些东西被 AI 自动化之后前端反而能把精力放到交互体验、业务复杂度和工程化建设上。最后分享一个实操小技巧生成完前端代码后别急着打开页面看效果先在浏览器 Console 里手动调用一次真实接口把返回结果打印出来再和 AI 生成的 TypeScript 类型逐字段对一眼。我做这个动作只需要十分钟但能提前消灭百分之八十的类型问题。真实接口返回的不规范字段、额外嵌套、异常 key在这一步全部暴露页面还没开始写地基已经验完了。