尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

基于 OpenAPI Specification(OAS)驱动前端开发,是目前 SDD 落地最成熟、收益最高的切入点。以下是完整的前端项目配置流程、工具链和实战案例

基于 OpenAPI Specification(OAS)驱动前端开发,是目前 SDD 落地最成熟、收益最高的切入点。以下是完整的前端项目配置流程、工具链和实战案例 基于 OpenAPI SpecificationOAS驱动前端开发是目前 SDD 落地最成熟、收益最高的切入点。以下是完整的前端项目配置流程、工具链和实战案例。一、整体架构流程┌─────────────────┐ 生成 ┌──────────────────┐ 消费 ┌──────────────┐ │ OpenAPI Spec │ ────────────→ │ TypeScript SDK │ ────────────→ │ React 组件 │ │ (后端提供/手写) │ hey-api │ TanStack Query │ │ Zod 校验 │ │ petstore.yaml │ openapi-ts │ MSW Mock │ │ 表单页面 │ └─────────────────┘ └──────────────────┘ └──────────────┘ ↑ │ └──────────────── 规范变更触发 CI 重新生成 ─────────────────────────┘二、工具链选型2026 推荐环节工具作用规范 → 代码hey-api/openapi-ts从 OpenAPI 生成 TS 类型、SDK Client、TanStack Query Hooks数据获取tanstack/react-query缓存、去重、后台刷新运行时校验zod对 API 响应做运行时校验防御性编程Mock 数据msw基于 OpenAPI 生成 Mock前后端并行开发规范校验redocly/cliLint OpenAPI 文件确保规范质量三、项目初始化与配置1. 目录结构my-frontend/ ├── specs/ │ └── petstore.yaml # OpenAPI 规范源文件 ├── src/ │ ├── api/ # 生成的代码只读不手动修改 │ │ ├── client.ts # Fetch Client │ │ ├── types.gen.ts # TypeScript 类型 │ │ ├── sdk.gen.ts # SDK 函数 │ │ └── tanstack/ │ │ └── react-query.gen.ts # TanStack Query Hooks │ ├── components/ │ ├── pages/ │ │ └── PetList.tsx │ └── mocks/ │ └── browser.ts # MSW 初始化 ├── scripts/ │ └── generate-api.ts # 生成脚本 ├── openapi-ts.config.ts # 生成器配置 └── package.json2. 安装依赖npminstalltanstack/react-querynpminstall-Dhey-api/openapi-ts hey-api/client-fetch tanstack/eslint-plugin-query redocly/cli msw zod3. 生成器配置openapi-ts.config.tsimport{defineConfig}fromhey-api/openapi-ts;exportdefaultdefineConfig({client:hey-api/client-fetch,// 使用原生 Fetch轻量input:specs/petstore.yaml,// OpenAPI 规范入口output:src/api,// 生成代码输出目录plugins:[hey-api/typescript,// 生成 TS 类型hey-api/sdk,// 生成 SDK 函数{name:tanstack/react-query,// 生成 React Query Hooks// 可选自定义 mutation 和 query 的命名},// 如需 Zod 校验可额外配置],});4. package.json Scripts{scripts:{api:generate:openapi-ts,api:lint:redocly lint specs/petstore.yaml,api:preview:redocly preview-docs specs/petstore.yaml,dev:npm run api:generate vite,build:npm run api:generate tsc vite build,test:vitest}}四、实战案例宠物商店PetstoreStep 1编写/获取 OpenAPI 规范specs/petstore.yamlopenapi:3.1.0info:title:Pet Store APIversion:1.0.0description:SDD 示例宠物商店接口规范servers:-url:http://localhost:3001/apipaths:/pets:get:operationId:listPetssummary:获取宠物列表parameters:-name:statusin:queryschema:type:stringenum:[available,pending,sold]default:available-name:limitin:queryschema:type:integerdefault:20responses:200:description:成功content:application/json:schema:type:objectproperties:data:type:arrayitems:$ref:#/components/schemas/Pettotal:type:integerpost:operationId:createPetsummary:创建宠物requestBody:required:truecontent:application/json:schema:$ref:#/components/schemas/CreatePetInputresponses:201:description:创建成功content:application/json:schema:$ref:#/components/schemas/Pet/pets/{petId}:get:operationId:getPetByIdsummary:根据 ID 获取宠物详情parameters:-name:petIdin:pathrequired:trueschema:type:stringresponses:200:description:成功content:application/json:schema:$ref:#/components/schemas/Petcomponents:schemas:Pet:type:objectrequired:[id,name,status]properties:id:type:stringname:type:stringcategory:type:stringstatus:type:stringenum:[available,pending,sold]tags:type:arrayitems:type:stringcreatedAt:type:stringformat:date-timeCreatePetInput:type:objectrequired:[name,status]properties:name:type:stringminLength:1maxLength:50category:type:stringstatus:type:stringenum:[available,pending,sold]default:availabletags:type:arrayitems:type:stringStep 2执行生成npmrun api:generate生成后的src/api/结构src/api/ ├── client.ts # Fetch Client 配置 ├── types.gen.ts # Pet, CreatePetInput 等类型 ├── sdk.gen.ts # listPets, createPet, getPetById 等 SDK 函数 └── tanstack/ └── react-query.gen.ts # useListPets, useCreatePet, useGetPetById 等 HooksStep 3配置 API Clientsrc/api/client.ts生成后微调或配置拦截器import{createClient,typeClientOptions}fromhey-api/client-fetch;exportconstclientcreateClient({baseUrl:import.meta.env.VITE_API_BASE_URL||http://localhost:3001/api,headers:{Content-Type:application/json,},});// 请求拦截器注入 Tokenclient.interceptors.request.use((request){consttokenlocalStorage.getItem(token);if(token){request.headers.set(Authorization,Bearer${token});}returnrequest;});// 响应拦截器统一错误处理client.interceptors.response.use((response){if(response.status401){window.location.href/login;}returnresponse;});Step 4前端页面使用React TanStack Querysrc/pages/PetList.tsximport { useState } from react; import { useListPets, useCreatePet } from ../api/tanstack/react-query.gen; import { z } from zod; // 运行时校验 Schema防御层 const PetSchema z.object({ id: z.string(), name: z.string(), category: z.string().optional(), status: z.enum([available, pending, sold]), tags: z.array(z.string()).optional(), createdAt: z.string().datetime().optional(), }); export default function PetList() { const [status, setStatus] useStateavailable | pending | sold(available); // 自动生成的 Hook类型安全 const { data, isLoading, error } useListPets({ query: { status, limit: 20 }, }); const createPet useCreatePet({ onSuccess: () { alert(创建成功); }, onError: (err) { alert(创建失败: ${err.message}); }, }); const handleCreate () { createPet.mutate({ body: { name: 新宠物, category: cat, status: available, tags: [cute, new], }, }); }; if (isLoading) return div加载中.../div; if (error) return div请求失败: {error.message}/div; // 运行时校验可选生产环境建议开启 const pets data?.data?.map(pet PetSchema.parse(pet)) ?? []; return ( div h1宠物列表/h1 select value{status} onChange{e setStatus(e.target.value as any)} option valueavailable可售/option option valuepending待定/option option valuesold已售/option /select button onClick{handleCreate} disabled{createPet.isPending} {createPet.isPending ? 创建中... : 新建宠物} /button table thead tr thID/th th名称/th th分类/th th状态/th th标签/th /tr /thead tbody {pets.map(pet ( tr key{pet.id} td{pet.id}/td td{pet.name}/td td{pet.category}/td td{pet.status}/td td{pet.tags?.join(, )}/td /tr ))} /tbody /table p总计: {data?.total} 条/p /div ); }Step 5MSW Mock 配置前后端并行开发src/mocks/handlers.tsimport{http,HttpResponse}frommsw;import{PetSchema}from../api/types.gen;exportconsthandlers[http.get(http://localhost:3001/api/pets,({request}){consturlnewURL(request.url);conststatusurl.searchParams.get(status)||available;returnHttpResponse.json({data:[{id:1,name:小白,category:dog,status,tags:[friendly],createdAt:newDate().toISOString()},{id:2,name:咪咪,category:cat,status,tags:[lazy],createdAt:newDate().toISOString()},],total:2,});}),http.post(http://localhost:3001/api/pets,async({request}){constbodyawaitrequest.json();returnHttpResponse.json({id:3,...body,createdAt:newDate().toISOString()},{status:201});}),];src/mocks/browser.tsimport{setupWorker}frommsw/browser;import{handlers}from./handlers;exportconstworkersetupWorker(...handlers);src/main.tsximport React from react; import ReactDOM from react-dom/client; import { QueryClient, QueryClientProvider } from tanstack/react-query; import App from ./App; const queryClient new QueryClient(); // 开发环境启用 MSW async function enableMocking() { if (process.env.NODE_ENV ! development) return; const { worker } await import(./mocks/browser); return worker.start(); } enableMocking().then(() { ReactDOM.createRoot(document.getElementById(root)!).render( React.StrictMode QueryClientProvider client{queryClient} App / /QueryClientProvider /React.StrictMode ); });五、CI/CD 集成.github/workflows/api-sync.ymlname:API Spec Syncon:push:paths:-specs/**# 规范文件变更-openapi-ts.config.tsschedule:-cron:0 2 * * *# 每天凌晨拉取后端最新规范jobs:generate:runs-on:ubuntu-lateststeps:-uses:actions/checkoutv4# 可选从后端仓库拉取最新 OpenAPI 文件# - run: curl -o specs/petstore.yaml https://api.backend.com/openapi.yaml-uses:actions/setup-nodev4with:node-version:20-run:npm ci-run:npm run api:lint# 先校验规范-run:npm run api:generate# 生成代码# 检查生成代码是否有变更有则自动提交-name:Check for changesrun:|if [ -n $(git status --porcelain src/api) ]; then git config user.name github-actions git config user.email actionsgithub.com git add src/api/ git commit -m chore: auto-generate api client from spec git push fi六、关键收益总结传统方式SDD OpenAPI 方式手写类型与后端容易不一致类型从规范自动生成100% 同步接口变更靠口头通知规范变更触发 CI代码自动更新Mock 数据手动维护MSW 基于规范自动 Mock前后端并行表单校验规则手写从规范minLength/maxLength/enum推导联调时才发现字段错误编译期类型检查 运行时 Zod 校验七、进阶从 OpenAPI 生成表单结合zodreact-hook-form可以从规范自动生成表单校验import{z}fromzod;import{useForm}fromreact-hook-form;import{zodResolver}fromhookform/resolvers/zod;// 从 CreatePetInput 类型反推 Zod Schema可进一步自动化constCreatePetFormSchemaz.object({name:z.string().min(1).max(50),category:z.string().optional(),status:z.enum([available,pending,sold]),tags:z.array(z.string()).optional(),});typeFormDataz.infertypeofCreatePetFormSchema;// 表单组件直接使用校验规则与后端 API 完全一致如果你需要我可以进一步提供多环境配置dev/staging/prod 不同 baseUrl文件上传接口的 OpenAPI 前端实现分页/无限滚动的 TanStack Query 最佳实践与后端团队协作的规范评审流程
返回列表