019 什么?Umi 中手动写 Mock 太麻烦了,那就让代码自己写代码吧

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第 21 天,点击查看活动详情

上节课我们介绍了如何在 Umi 项目中引入 mockjs 来快速助力和完善前后端开发分离流程。

19.jpg

但是 lucaslz 朋友还是觉得太麻烦了,我觉得可能有同样想法的朋友还不少。

首先这里需要一个前提条件,服务端必须通过 swagger 提供给前端 api 的文档,如果你们的前端是通过 world 或者聊天窗口直接发接口文档给你的,那你用不了这个方案。

在 Umi 的项目中,我们有一个最佳实践的推荐目录 src/service 目录,用来存放与服务端发起的请求,或者说就是接口文档的前端代码翻译。

这在工作中,需要写很多重复的样板代码,虽然早起我们也通过微生成器等工具来简化了我们的工作,但是在真实的开发工作中,涉及到接口的变更,我们也需要人工的去迭代这些样板文件。

这些工作其实会站到将近四分之一的工作量。因此我们就设想着能不能通过后端模型直接生成对应的数据,甚至生成前端需要的代码。

其实早在3年前我们就意识到了这个问题,并且开始“偷懒”。我们建立了一个工具,叫做米莱狄,它能够通过 swagger 的 url 自动化生成 service 文件和 mock 文件。这很好用,但是由于那时候我们是开源社区小透明,所以知道这工具的人很少,其实在 alitajs 社区中还有很多类似好用的工具,以后有机会我会分享给更多的朋友。

1901.jpg

今天要分享的方案,是在 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

效果

执行日志如下:

> [email protected] openapi /Users/congxiaochen/Documents/umi4-course
> umi openapi

info  - Using Request Plugin
Using openapi Plugin
[openAPI]: ✅ 成功生成 service 文件
[openAPI]: ✅ 生成 mock 文件成功
[openAPI]: execution complete

自动生成如下文件:

1902.jpg

不仅仅是代码

是不是觉得很神奇了,开始心动了,但是其实这个插件给你的不仅仅是代码,还有文档,我相信有过真实开发经历的朋友,一定都遇到过一个问题,在本地连调的时候,服务端重启了,你需要等他重启,5-10分钟时最少的了。有些朋友回想说这不就是合理摸鱼时间吗?但是我觉得只有主动摸鱼才叫摸鱼,被动摸鱼,那就是“卡壳”。

这时候你就可以在开发环境中访问 /umi/plugin/openapi 路由看到接口文档页面了。

1903.jpg

实现

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 如果你有任何想了解的内容,可以多在评论区和我交流哦。

猜你喜欢

转载自juejin.im/post/7112427681454686239