起因:一个后端框架+恰好的前端教程
最近我一直在折腾一个用 Rust 写的后端框架
在给它集成 OpenAPI 的过程中,我发现它生成的规范文档还挺全面的,而且数据结构清晰,解析起来也不复杂。
当时就冒出一个想法:既然 OpenAPI 规范这么标准,为什么好像没人基于此写一个能自动生成前端类型和客户端的工具呢?每次前后端联调,手动同步类型定义确实是个挺烦人的事。
正好那段时间在看 Vite 插件相关的教程,就想着,要不自己动手试试?于是,花了一两天时间,就折腾出了这么个东西:vite-plugin-openapi-ts。
这个插件主要做了什么
它的核心功能很简单,就是根据你的 OpenAPI 文档,自动生成两样东西:
- TypeScript 类型定义:所有接口的请求参数、返回值,都有对应的类型。
- 类型安全的 API 客户端:一个可以直接调用的函数,帮你把请求发出去。 这样一来,前端就不用再手动维护这些类型了,后端文档一更新,前端这边重新跑一下项目,类型就自动同步了。
怎么用
用起来挺直接的,大概分三步。
第 1 步:安装
pnpm add -D vite-plugin-openapi-ts第 2 步:配置 vite.config.ts
在 vite.config.ts 里加上这个插件,指向你的 API 文档地址就行。
import { defineConfig } from 'vite';import openapiPlugin from 'vite-plugin-openapi-ts';export default defineConfig({ plugins: [ openapiPlugin({ // 你的后端 API 文档地址 url: 'http://localhost:8080/v3/api-docs', // API 请求的基地址 (可以省略,你不写就是url的根地址) baseUrl: 'http://localhost:8080', // 生成文件的存放目录,可选,默认是 'src/openapi' (如果你改位置了,记得检查一下tsconfig.json里include了没有...) outputDir: 'src/openapi', // 缓存,这个默认就是true,如果url baseUrl 以及 请求下来的json/yaml的sha256一样的话,就不重新解析生成了,不过每次都请求也是有点费时间 enableCache: true, }) ]});配置好之后,运行 pnpm dev,插件就会自动在 src/openapi 目录下生成相关文件。
第 3 步:在代码里调用
现在你可以在代码里直接导入生成的客户端来发请求了。 它最直观的好处就是,如果你写错了,TypeScript 会直接在编辑器里给你标红,在编译阶段就能发现问题。
import apiClient from './openapi';// 正确的,路径参数和返回值都有类型提示const { data } = await apiClient( '/users/{id}', 'get', { params: { id: '123' } });// 如果你少传了必需参数,这里会直接报错// const { data: errorData } = await apiClient(// '/users/{id}',// 'get',// {// // params: { id: '123' } // 注释掉必需参数,IDE 里这行就会爆红// }// );// 如果你引用了一个不存在的路径,或者方法不对,也会直接报错// apiClient('/non-existent-path', 'get'); // 这行代码在写的时候就会提示错误// apiClient('/users/{id}', 'put'); // 如果不支持 put 方法,同样会报错// POST 请求,请求体的类型也是安全的const { data: newUser, response } = await apiClient( '/users', 'post', { body: { name: 'John', email: 'john@example.com' } });这种“类型非常安全”的感觉,能帮你避免很多低级错误,主要还是有类型提示,response也有。
除了生成类型,还顺手加了一些功能
在开发过程中,我发现只有类型生成还不够,一些常见的请求处理场景也需要支持。所以,这个插件生成的客户端也包含了一些比较实用的功能。
- 请求/响应拦截器:方便统一处理认证 Token、错误码等。
- 请求取消与超时:支持
AbortController,可以避免组件卸载后还在发请求。 - 自动重试:对于网络波动等临时错误,可以设置自动重试。
- 文件上传:上传文件时,只要把
File对象放到body里,它会自动处理成FormData。 这些功能让生成的客户端不仅仅是个类型工具,更像一个能直接在项目里用的请求库。
最后想说的话
最后想说明一下,这个插件目前是我个人兴趣驱动的项目,主要解决自己遇到的问题。所以对于个人项目或者小团队来说,应该是够用的。 如果是大型多人项目,可能需要多评估一下。不过好在它本身没什么侵入性,就是一个封装好的客户端,你完全可以引入试试,即使不用也完全没影响。 如果你觉得这个思路不错,或者正好有类似的需求,可以试试看,也欢迎提 Issue 和 PR。 项目地址在这里: