上节课我们介绍了如何在 Umi 项目中引入 mockjs 来快速助力和完善前后端开发分离流程。
但是 lucaslz 朋友还是觉得太麻烦了,我觉得可能有同样想法的朋友还不少。
首先这里需要一个前提条件,服务端必须通过 swagger 提供给前端 api 的文档,如果你们的前端是通过 world 或者聊天窗口直接发接口文档给你的,那你用不了这个方案。
在 Umi 的项目中,我们有一个最佳实践的推荐目录 src/service 目录,用来存放与服务端发起的请求,或者说就是接口文档的前端代码翻译。
这在工作中,需要写很多重复的样板代码,虽然早起我们也通过微生成器等工具来简化了我们的工作,但是在真实的开发工作中,涉及到接口的变更,我们也需要人工的去迭代这些样板文件。
这些工作其实会站到将近四分之一的工作量。因此我们就设想着能不能通过后端模型直接生成对应的数据,甚至生成前端需要的代码。
其实早在3年前我们就意识到了这个问题,并且开始“偷懒”。我们建立了一个工具,叫做米莱狄,它能够通过 swagger 的 url 自动化生成 service 文件和 mock 文件。这很好用,但是由于那时候我们是开源社区小透明,所以知道这工具的人很少,其实在 alitajs 社区中还有很多类似好用的工具,以后有机会我会分享给更多的朋友。
今天要分享的方案,是在 ant design pro 中使用到的 openAPI 插件。
openAPI 对于后端是有一定要求的,但是工作量远远小于维护一个文档的成本,如果维护一个文档,那么每次更新完代码就需要重新编辑一遍文档。而使用 openAPI 的方式只要接入 swagger 然后做一些配置就可以生成一个界面,如果你使用的是 python 或者是 java,那么接入会变得异常简单。详细的接入步骤可以看 swagger 的官方文档。这里主要介绍前端如何使用。
后端接入完成 swagger 之后,我们可以访问 swagger 生成的文档,一般来说都是 http://localhost:8080/swagger-ui.html
,访问页面我们可以拿到一个 openAPI 的规范文件。
使用
安装插件
pnpm i @umijs/max-plugin-openapi swagger-ui-react 复制代码
配置
然后在 config/config.ts
中配置 openAPI 的相关配置。
plugins: [ // ... 其他插件 // 这是当前的目录,最近正在调整这个插件,如果你这么写报错了,请访问官网查看最新用法 require.resolve("@umijs/max-plugin-openapi/dist/openapi"), ], openAPI: { // 这里使用服务端提供的url schemaPath: "https://gw.alipayobjects.com/os/antfincdn/M%24jrzTTYJN/oneapi.json", mock: true, } 复制代码
配置命令
然后在 package.json
中配置 scripts 命令。
"scripts": { "start": "umi dev", "openapi": "umi openapi", "build": "cross-env ANALYZE=1 umi build" }, 复制代码
执行命令
pnpm openapi 复制代码
效果
执行日志如下:
> umi4-course@1.0.0 openapi /Users/congxiaochen/Documents/umi4-course > umi openapi info - Using Request Plugin Using openapi Plugin [openAPI]: ✅ 成功生成 service 文件 [openAPI]: ✅ 生成 mock 文件成功 [openAPI]: execution complete 复制代码
自动生成如下文件:
不仅仅是代码
是不是觉得很神奇了,开始心动了,但是其实这个插件给你的不仅仅是代码,还有文档,我相信有过真实开发经历的朋友,一定都遇到过一个问题,在本地连调的时候,服务端重启了,你需要等他重启,5-10分钟时最少的了。有些朋友回想说这不就是合理摸鱼时间吗?但是我觉得只有主动摸鱼才叫摸鱼,被动摸鱼,那就是“卡壳”。
这时候你就可以在开发环境中访问 /umi/plugin/openapi
路由看到接口文档页面了。
实现
1、通过 http 请求 openAPI
配置中的 schemaPath
地址。
openAPI: { schemaPath: "https://gw.alipayobjects.com/os/antfincdn/M%24jrzTTYJN/oneapi.json", } 复制代码
2、将请求回来的参数保存在临时文件 node_modules/umi_open_api/umi-plugins_openapi.json
中。
umi-plugins_openapi.json
{ "openapi": "3.0.1", "info": { "version": "1.0.0" }, "servers": [ ], "paths": { "/api/currentUser": { "get": { "tags": [ "api" ], "description": "获取当前的用户", "operationId": "currentUser", "responses": { "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CurrentUser" } } } }, "401": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } }, "x-swagger-router-controller": "api" } }, "components": { "schemas": { } } } 复制代码
3、生成临时的页面文件 src/.umi/plugin-openapi/openapi.tsx
import { useState } from "react"; import SwaggerUI from "swagger-ui-react"; import "swagger-ui-react/swagger-ui.css"; const App = () => { return (<SwaggerUI url={`/umi-plugins_openapi.json`} />); }; export default App; 复制代码
4、通过中间件将 /umi-umi-plugins_openapi
映射到临时文件中
api.addBeforeMiddlewares(() => { return [serveStatic('umi-plugins_openapi')]; }); 复制代码
5、为 Umi 手动添加一个可访问的路由
api.modifyRoutes((routes) => { routes['umi/plugin/openapi'] = { path: '/umi/plugin/openapi', absPath: '/umi/plugin/openapi', id: 'umi/plugin/openapi', file: 'src/.umi/plugin-openapi/openapi.tsx', }; return routes; }); 复制代码
到此文档展示的功能完成。
6、定义 openapi 命令
api.registerCommand({ name: 'openapi', fn: async () => { const openAPIConfig = api.config.openAPI; genAllFiles(openAPIConfig); }, }); 复制代码
这使得我们可以通过执行 umi openapi
来执行一些 node 操作,比如上面的 genAllFiles
7、 定义 genAllFiles 函数
找到生成文件的路径,比如 mock 文件和 services 文件的等,然后根绝 swagger 的内容生成对应的文件,实现较长,这里就不贴代码了,感兴趣的朋友可以查看umi-preset-pro,这是我为 ant design pro@next 的发布,创建的一个 presets。后续里面会有其他 pro 专用的插件收录,感兴趣的朋友可以关注一下。
感谢阅读,关于 Umi 如果你有任何想了解的内容,可以多在评论区和我交流哦。