问题与效果
你是否烦恼:
- 每次接口变动都要改对应前端请求代码?
- 类型提示很好用但懒的写?
- js 项目不想迁移到 ts 但也想要类型提示?
就现在,仅需3步,让项目请求代码进入自动生成时代!
- 代码生成效果
- 代码提示效果
TS代码,入参提示
JS代码,响应提示
想实战的小伙伴可以直接到项目 zdminjs/ara 安装体验。
下面是原理与设计思路介绍。
背景
实际上规模大点的团队都会想做诸如前端代码生成之类的基础设施。这部分工作简单却繁琐,不考虑类型注释部分,请求代码通常占全部代码的5%左右,让5%的代码先进入工业化也是提效一小步了。
请求代码生成原理上也不复杂,请求代码和后端接口强绑定,本身就和后端提供的 Swagger/OpenAPI 文档一一相关,那么从 Swagger/OpenAPI 文档到代码文本就是很自然的想法。
关键点在于,如何让这种生成工具具备跨项目、跨公司的接入与自定义能力?
复用难点与解法
- 请求库的自定义能力 => 自定义代码、依赖
- Swagger/OpenAPI 文档的鉴权问题 => 浏览器插件
请求库的自定义能力
与后端项目只需关注数据结构,项目间通过服务纯以请求方式隔离,项目内无需关心底层用什么工具发送了请求不同。前端项目通常会封装底层的请求库,做一些自定义操作。常见的如封装 fetch、封装 axios 等,几乎都有各自的拦截器行为,以及框架内的,比如小程序,指定底层,无法更改。
如果工具封装这部分内容,最直接的问题就是:
- 项目适配成本巨大,老旧项目几乎无法接入
- 选型决策困难,对比 axios 等毫无优势,全是风险点
因此,请求库的自定义能力就是首要需考虑的问题。
接口文档的鉴权问题
通常 Swagger/OpenAPI 的接口文档会放在鉴权后。
对不同的鉴权流程,不论是:
- 用代码方式去固定或配置
- 让后端同学将文档开放
都会提升接入成本。
解决方法
- 对于第一个问题,解法很明确,就是允许用户自定义请求代码,允许用户自定义请求库。
- 对于第二个问题,考虑通过浏览器插件,复用浏览器的鉴权流程。
用户阅读 Swagger/OpenAPI 文档本身就是通过浏览器,本身就要进行鉴权。那么在浏览器上提供一个鉴权后的代码生成按钮,点击一键生成,就是很自然的操作流程。
模块设计
- Q:能不能全用浏览器插件解决?
- A:理论上可以,实际上不划算。
请求代码生成的整个流程为:
- 读取接口文档
- 接口文档转换为代码
- 代码写入项目
浏览器插件本质是带 SDK 的网页环境,仅在步骤1中存在优势,在 2、3 是纯劣势。而且在步骤 2 中还需要解决用户自定义代码带来的问题。因此,考虑将 2、3 步骤放在项目里,在 node 环境中解决。
现代的前端项目本身具备 node 环境,只需提供一个处理 2、3 步骤的 node 本地服务,整个流程就能串起。
因此,模块就是:浏览器插件 + node 本地服务。
考虑到 2、3 步骤只在开发过程中需要,而开发过程普遍使用 devServer,那么使用构建工具插件,将 node 本地服务的启停与 devServer 绑定,即可简化配置上手流程。
整体模块即为:浏览器插件 + 构建工具插件(基于本地服务)。
功能点实现
再捋下流程,接口文档本质是一个 json 对象,而代码本质上是纯文本文件,也就是字符串。
所以本质就是将一个 json 对象转成代码字符串,然后写入到项目文件里。
读取接口文档
后端同学提供的 swagger 或 openapi 文档,加载时会去前面提到的 json 数据。
那么这里,就是浏览器插件是否提供了获取页面请求响应内容的 sdk?
是有的,但是只能在开发者工具中使用。考虑到工具也需要 UI,那么就开发一个类似 Vue DevTools 的工具就好了。
代码生成
再次,代码本质是字符串。对于 ts/js 代码而言,可以直接通过 typescript 构建代码对应的 ast,然后再让 typescript 将 ast 输出为代码即可。
- Q:为什么用 ast 不用字符串拼接
- A:因为 ast 是已有标准,上限更高
除了普通的请求函数代码外,还需要生成对应的类型代码。
类型代码这块,直接用已有的成熟库即可,如果要造轮子,也可以用 typescript 自行实现。
代码写入项目
有了代码的字符串后,输出成 ts/js 文件就很简单了,用 node 创建文件并写入就好了。
这里可以用 unplugin 为主流构建工具编写插件。
有了项目插件,工具就可以获取到项目位置,同时也能给开发者提供自定义配置的地方。