“本文首发于个人博客,转载请注明出处html
”前端
网上时不时就能看到一些求助帖,大意是先后端集成所产生的一些争执,其实集成的时候若是能有一些”规范“,这件事情能够很简单。ios
本文跟技术栈强相关,可是理论上从里面抽离出来的方法论能够实践在任意的技术栈上,只须要投入一点点时间和精力写一个小工具就行了,下面是本文所用到的一些技术栈:git
其中最后一项就是上面提到的须要本身去实现的小工具,这里我是把组里以前给redux用的工具改了一版,先是从 swagger2.0 升级到 openAPI 标准,而后改成生成 SWR 的代码而不是redux的,具体工具怎么使用能够看个人 github,里面有详细的 readme 和 example。这个工具虽然简单,倒是先后端集成不可或缺的重要组成部分,稍后咱们会讲到。程序员
而后 SWR 是一个很酷的用于获取远端数据的一个基于 React hooks 的请求库。它实现了 HTTP 规范中的 stale-while-revalidate
,即其会先使用 catch 中已存在的 data 先渲染页面,而后发送新的请求去验证 catch 中的 data 是否为最新,若是已是最新则什么都不作,若是不是最新则更新本地的 catch 而后使用最新的 catch 从新渲染页面。github
这样作的好处是能够极大地提高用户体验,用户在重复浏览同一页面时,若是页面数据更新不频繁则没有任何等待时间。在新项目上使用几个月后,我欣喜地发现 SWR 登上了 ThoughtWorks 最新一期的技术雷达,和 Recoil、Svelte 一块儿暂时位于评估象限。npm
SWR in tech radarjson
不过技术雷达也一针见血地指出了 SWR 的缺陷:redux
“咱们的开发者在使用 SWR 时得到了很好的开发体验,而且由于数据老是显示在屏幕上,从而显著提高用户体验。然而,咱们提醒团队,只有当应用程序返回过期数据是合适的时候,才能使用 SWR 缓存策略。要注意,HTTP 一般要求缓存要用最新的响应返回给请求,只有在须要_很是慎重的场景_下,才会容许返回过期的响应数据。axios
”
也就是说,若是你的坏境对数据更新的要求极高,须要实时拿到最新的数据的话,不适合使用 SWR。
TypeScript 如今几乎成为了一门前端必上的技术栈,相比 JavaScript,其提供的类型系统可以保证程序员们常犯的”低级错误“在写代码时就暴露出来。
但也是因为其类型系统,咱们在集成后端 API 时须要写一堆麻烦的接口类型,好比一个 request 的参数,这个 response 的数据类型等等。
而这些接口类型实际上是后端定义的,咱们实际上是在依赖后端写的接口来写类型。这就很尴尬了,后端改了接口,前端也得跟着改类型,这多麻烦,后面咱们会一块儿解决这个问题。
要解决一个问题,那么咱们首先应该作的是想清楚为何会出现这样的问题。
首先咱们来回忆一下常规的开发过程:拿到需求,先后端讨论出接口的各类参数,开始写代码,这中间可能后端(前端)发现有问题,而后改接口,而后差很少写好的接口得从新改,改类型,改参数。
这是常规的,不常规的呢?后端本身定好接口的参数,而后告诉你他要啥给你啥,而后你按照他给的写,写好发现不能用,去找他,他说接口改了,你从新改下。那还能咋说,只能网上对线了。
说白了就是,先后端讨论好的东西可能会变(甚至都没有通过讨论,由单方面直接决定好了),变了以后因为各类各样的缘由没能及时同步信息,即便及时同步了,改接口代码也是一件烦人的事情。
咋办?
首先,咱们须要搞清楚什么是契约测试?
契约测试,又叫”消费者驱动的契约测试“(Consumer-Driven Contracts,简称CDC)。其中有两个角色,一个消费者,一个生产者。由消费者提供一份本身的”需求清单“(契约,约定好request和response),而后生产者根据“清单”进行相应实现。以后双方依赖于这份契约进行测试和实现。
其实契约测试将依赖双方作了一个相似于解耦的操做,从消费者依赖于生产者变成双方依赖于消费者提供的契约。咱们是否是能够运用这个思想呢?
其实大多数项目里已经有一份契约了,没错,就是 swagger。只不过这份契约是生产者提供的,并且由生产者决定上面有啥,消费者无法决定。
可是其实咱们能够将这份契约作一个转换。swagger 上一般会给出 API 的详细信息,包括 request 的参数和 response 长什么样子。并且其实 swagger 只是一份 json 文件,咱们所看到的 swagger-ui 是后端的 lib 自动生成的。那么咱们是否是能够拿到这份 json 文件。解析后直接生成前端须要的 request 和类型呢?
这样带来了几个好处:
说了这么多都是理论,谁知道效果呢?不要紧,咱们直接上代码,下面全部的代码均可以在连接里面找到。
首先看一下这个example的目录:
“. |____swagger | |____openAPI.json |____types.ts |____request | |____api.ts | |____useRequest.ts | |____client.ts |____page.tsx
”
其中 swagger 文件夹下是我从网上生成的 openAPI 规范的 swagger 文档。
request 文件夹下有三个文件:
这东西怎么用呢?
首先固然是安装这个包 npm i @openapi-integration/swr-request-generator -D
而后在项目的根目录添加一个配置文件,里面能够配置生成文件的输出目录,文件名,须要提早引入的方法,从哪里拿到 swagger 文件等(具体能够看readme)
而后跑一下 npm run ts-codegen
,就会在你配置的相应生成对应的 API 文件。
好比下面这个方法就是生成的:
``import { ISWRConfig, useRequest } from "./useRequest";
import { IResponseError } from "../types";
import { client } from "./client";
export const useDownloadUsingGetRequest = (
{
id,
}: {
id: string;
},
SWRConfig?: ISWRConfig<IResource, IResponseError>,
) =>
useRequest<IResource, IResponseError>(
{
url: /${id}
,
method: "get",
},
SWRConfig,
);
export interface IResource {
description?: string;
file?: IFile;
filename?: string;
inputStream?: IInputStream;
open?: boolean;
readable?: boolean;
uri?: IUri;
url?: IUrl;
}
``
而你只须要在调用的时候直接:
`const = { data, error } = useDownloadUsingGetRequest({ id: "id"})
`
假如后端改了代码,这个接口不要 id 了,要 name,你只须要从新跑一次npm run ts-codegen
,而后这个方法就会更新,TypeScript 就会报错,告诉你这里要的是 name 不是 id,若是 response 的结构也改了,那么所生成的文件里面的 response 的类型也会跟着变, TypeScript 依然会提醒你 response 结构的改变。
这样一来接口不管怎么变其实前端都不在乎,顶多就是跑一遍命令,从新穿个参数就行了,大大提高开发效率,下降内耗。