我在 Taro 小程序项目里实践的 API First + AI 编程方式
最近我在一个 Taro + React + TypeScript 的微信小程序项目里,逐渐形成了一套比较顺手的开发方式:
API First 负责把后端契约稳定下来,AI 负责在契约之上读项目、拆业务、补实现、查风险。
它不是「让 AI 随便生成一堆代码」,也不是「前端等接口好了再手写 service」。我的做法是把接口契约作为开发起点,把生成代码作为类型边界,再让 AI 在这个边界内做具体业务开发。
这篇文章结合项目真实结构,整理一下这套工作流------重点讲怎么协作,而不是贴代码。
项目背景
项目是一个面向微信小程序的移动端工程,技术栈大致是 Taro、React、TypeScript、NutUI、Zustand、Zod、Tailwind 小程序适配,以及基于 OpenAPI 的客户端生成。
业务上有登录、活动、报名、协议、我的、行程、住宿、拍摄预约、素材下载等流程。它不是纯展示项目,页面之间存在比较强的状态关系:
- 登录成功后,要根据当前活动列表决定进入活动页还是我的页。
- 活动页的服务模块来自接口返回的活动服务配置,不是前端写死。
- 无当前活动时,Tabbar 只显示「我的」。
- Token 过期后,需要统一清理登录态、用户信息、当前活动缓存,并重新进入登录页。
- 图片、文件、素材等资源还要处理鉴权访问。
这类项目最怕两件事:接口字段靠人肉记忆,页面里到处写散装类型;AI 不理解项目约束,生成一段「局部正确、整体不合适」的代码。
所以我现在的核心思路是:先用 API First 把接口契约落成代码,再让 AI 基于这些代码做业务开发。
一、接口契约先行
项目里接口契约来自 mp.yaml。通过 @hey-api/openapi-ts 生成到 src/client/,包括 API 方法、请求与响应类型,以及适配 Taro 运行时的客户端。
这意味着前端不是先手写一堆散装请求,而是先让契约生成可调用的方法与类型。页面和 store 直接消费生成结果,接口字段、入参、返回值、错误结构不再靠猜。
AI 参与开发时,也不是凭空编一个接口名,而是先读 src/client/ 里已经导出了什么,再根据生成类型去写业务逻辑。
这一步很关键。如果上下文是「自然语言描述」,AI 会有很多发挥空间;如果上下文是「OpenAPI 生成出来的类型和函数」,它的发挥空间就被收束在项目真实契约里。
接口有变更时,先更新契约再重新生成;开发期也可以开 watch,减少手工同步。
二、生成客户端要接入真实运行时
API First 并不只是「生成类型」,还要把生成出来的 client 接到小程序真实运行时里。
项目里做了自定义 Taro client 插件,把生成层适配到 Taro.request,同时保持统一的调用模型。契约、类型、请求实现、业务调用连成一条链,而不是只停留在「有个 Swagger 文档」。
页面不需要关心底层请求拼装;AI 写业务时,只需要调用生成好的方法,在类型边界内组织 UI 和交互。
三、横切逻辑放在入口层
鉴权、baseUrl、401 处理这类横切关注点,集中在应用入口统一配置,而不是让每个页面各自处理。
典型做法包括:请求拦截器统一注入 Token;响应拦截器统一处理 401,并走统一的登出与清理流程;清理范围覆盖 token、用户信息、当前活动等跨页面状态;最后跳转登录页。
这部分对 AI 协同同样重要。我会明确告诉 AI:不要在页面里重复拼 Authorization;不要绕过生成 client 自己写请求;不要在单个业务组件里私自处理 401;登录态清理必须走项目已有的统一方法。
AI 写代码前先知道这些边界,就不会把横切逻辑散落到各个页面和弹层里。
四、Store 是接口和页面之间的缓冲层
在这个项目里,很多接口不是直接散落在页面里,而是被放进 Zustand store。
以当前活动列表为例:store 内部调用生成接口,并处理请求复用、版本控制、登出后的旧请求回写等问题。页面只订阅 store 状态,不重复发明一套请求逻辑。
如果只是让 AI「请求当前活动列表」,它很容易在页面生命周期里直接调接口------短期能跑,长期会遇到多页面重复请求、登出后旧请求覆盖新状态、Tabbar 与各页状态不一致等问题。
现在有了 API First 和 store 边界,AI 的任务就变成:在已有 store 语义里补业务,而不是重新发明一套状态管理。
五、页面逻辑围绕接口数据组织
活动页是一个典型例子。页面通过 store 拿当前活动;加载时以接口返回为准决定跳转;无活动时切到我的页;Tabbar 根据活动数量动态显示。
服务模块也不是写死所有能力,而是接口返回活动服务配置,前端按服务 id 渲染对应业务模块,模块内部再调用自己的生成接口。
AI 改活动页或新增一个服务模块时,需要同时理解:接口返回了什么、store 里已有什么状态、页面路由与 Tab 跳转规则是什么。这种上下文比一句「帮我加个模块」清晰得多。
六、AI 在这套流程里的位置
我现在不会让 AI 脱离接口契约自由发挥。更常见的方式是给它一个任务,然后要求它按这个顺序来:
- 先读契约文件或生成后的
src/client/。 - 确认已有接口方法、类型、入参和返回值。
- 再读业务页面、store、组件边界。
- 给出改动方案和风险点。
- 小范围修改。
- 跑构建或至少做 diff 检查。
比如要做拍摄预约相关能力,我不会让 AI 直接写一个组件。我会让它先确认生成客户端里是否已有查询档期、查询我的预约、创建预约等接口与对应类型,再看这个服务模块从哪进入、activityId 怎么传、刷新机制怎么驱动。
换句话说,我不是让 AI「猜接口」,而是让 AI「读接口」。
七、API First 能显著降低 AI 幻觉
AI 写业务代码时,常见幻觉包括:编不存在的接口或字段、搞错字段类型、忘记响应结构、自己造 request helper、错误处理与项目风格不一致。
API First 可以把这些问题压下去很多。因为 AI 可以直接看到当前导出了哪些 API、参数与返回类型是什么、哪些字段可选、哪些错误已在类型里描述。
只要被要求优先使用 @/client 中已有导出,就不太容易跑偏。这比在 prompt 里口头描述接口可靠得多。
八、有了契约边界,验收会更具体
以前验收 AI 产出时,很容易停留在风格层面。现在有了契约边界,我会更关注这些工程问题:
- 有没有走生成 client,而不是手写请求?
- 有没有正确使用生成类型?
- 空态、加载态、错误态是否处理?
- 有没有重复处理 Token 或 401?
- store 是否处理了并发请求和登出后的旧请求回写?
- 页面是否保留了路由契约,比如 Tab 页是否正确使用 switchTab?
- diff 里有没有混入无关修改?
这些都是项目里的真实约束,不是泛泛的「代码好不好看」。
九、一个完整任务通常怎么跑
第一步,更新或确认接口契约。 后端有变化时先更新 mp.yaml,重新生成客户端。
第二步,让 AI 读生成结果。 先看 src/client/ 导出,再定位本次需求相关的页面、store 和组件。
第三步,让 AI 先出方案。 说清楚改哪些文件、接口调用放在哪一层、页面状态怎么处理、是否影响登录态、Tabbar、分包与路由、需要验证哪些场景。
第四步,小范围实现。 按现有模式改,不做大范围重构。已有 store 就放 store,已有 modal 体系就沿用,已有 Tab 跳转工具就不另写一套。
第五步,构建和 diff 检查。 至少跑小程序构建,再看 diff,确认没有混入无关修改。
十、这套方式带来的变化
这套 API First + AI 的方式,对我最大的帮助不是「少写几行代码」,而是降低了复杂业务里的不确定性。
以前常见问题是:接口字段理解不一致、手写类型和真实返回不一致、页面里散落临时判断、改一个接口影响多个页面很难查全、AI 容易脱离项目风格。
现在会好很多。接口变化先进入契约文件,再进入生成客户端;AI 读到的是生成后的事实,而不是口头描述。
整条链路是:契约文件 → 代码生成 → 统一鉴权与错误处理 → store 封装业务状态 → 页面与组件消费契约 → AI 在边界内补实现、查风险。链路越清楚,AI 越可靠。
十一、我给 AI 的约束清单
在这个项目里,我通常会明确这些要求:
- 接口调用优先从
@/client导入。 - 不要手写重复的 Taro 请求,不要自己拼 API 地址。
- 不要在页面里重复写 Token 注入,不要绕过统一 401 处理。
- 类型优先使用生成类型。
- store 已有状态语义时,优先复用 store。
- 路由跳转遵循小程序规则,Tab 页优先 switchTab。
- 不要为实现一个需求顺手重构无关模块。
- 修改后必须看 diff,能构建就构建。
约束越明确,AI 输出越接近真实项目里的工程改动。
十二、总结
我现在理解的 API First,不是「接口文档先写好」这么简单。它应该是一条完整链路:后端契约先进入 OpenAPI;前端用生成工具获得 API 方法与类型;请求客户端适配项目运行时;鉴权与错误处理放在统一入口;页面与 store 只消费稳定边界;AI 在边界内做实现和风险检查。
这套方式和 AI 很搭。因为 AI 最怕上下文模糊,API First 刚好提供了非常明确的上下文:方法名、参数、类型、返回值、错误结构都是真实存在的。
所以我现在越来越少让 AI「从零写一个功能」,而是让它沿着项目已有链路工作:
先读契约,再读业务;先确认边界,再写代码;先小步实现,再构建验证。
对我来说,这就是目前最舒服、也最稳的一种 AI 编程方式。