前端晋升必备:请求代码自动生成

59 阅读5分钟

问题与效果

你是否烦恼:

  • 每次接口变动都要改对应前端请求代码?
  • 类型提示很好用但懒的写?
  • js 项目不想迁移到 ts 但也想要类型提示?

就现在,仅需3步,让项目请求代码进入自动生成时代!

  • 代码生成效果

代码生成效果

  • 代码提示效果

TS代码,入参提示

TS代码,入参提示

JS代码,响应提示

JS代码,响应提示

想实战的小伙伴可以直接到项目 zdminjs/ara 安装体验。

下面是原理与设计思路介绍。

背景

实际上规模大点的团队都会想做诸如前端代码生成之类的基础设施。这部分工作简单却繁琐,不考虑类型注释部分,请求代码通常占全部代码的5%左右,让5%的代码先进入工业化也是提效一小步了。

请求代码生成原理上也不复杂,请求代码和后端接口强绑定,本身就和后端提供的 Swagger/OpenAPI 文档一一相关,那么从 Swagger/OpenAPI 文档到代码文本就是很自然的想法。

关键点在于,如何让这种生成工具具备跨项目、跨公司的接入与自定义能力?

复用难点与解法

  • 请求库的自定义能力 => 自定义代码、依赖
  • Swagger/OpenAPI 文档的鉴权问题 => 浏览器插件

请求库的自定义能力

与后端项目只需关注数据结构,项目间通过服务纯以请求方式隔离,项目内无需关心底层用什么工具发送了请求不同。前端项目通常会封装底层的请求库,做一些自定义操作。常见的如封装 fetch、封装 axios 等,几乎都有各自的拦截器行为,以及框架内的,比如小程序,指定底层,无法更改。

如果工具封装这部分内容,最直接的问题就是:

  • 项目适配成本巨大,老旧项目几乎无法接入
  • 选型决策困难,对比 axios 等毫无优势,全是风险点

因此,请求库的自定义能力就是首要需考虑的问题。

接口文档的鉴权问题

通常 Swagger/OpenAPI 的接口文档会放在鉴权后。

对不同的鉴权流程,不论是:

  • 用代码方式去固定或配置
  • 让后端同学将文档开放

都会提升接入成本。

解决方法

  • 对于第一个问题,解法很明确,就是允许用户自定义请求代码,允许用户自定义请求库。
  • 对于第二个问题,考虑通过浏览器插件,复用浏览器的鉴权流程。

用户阅读 Swagger/OpenAPI 文档本身就是通过浏览器,本身就要进行鉴权。那么在浏览器上提供一个鉴权后的代码生成按钮,点击一键生成,就是很自然的操作流程。

模块设计

  • Q:能不能全用浏览器插件解决?
  • A:理论上可以,实际上不划算。

请求代码生成的整个流程为:

  1. 读取接口文档
  2. 接口文档转换为代码
  3. 代码写入项目

浏览器插件本质是带 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 为主流构建工具编写插件。

有了项目插件,工具就可以获取到项目位置,同时也能给开发者提供自定义配置的地方。