【工程化】开发阶段没有接口,如何模拟后端接口请求

前言

在开发的过程中,会遇到后端文档出来了但接口没出来,或者是联调的时候接口有问题,那么前端的调试就有困难了。自己之前遇到这种情况是前端写死假数据,感觉有点傻哈哈,不灵活还有一定的风险。

这里举例个人积累过的方案,希望能帮助到大家。


Mock-server

这个方案了解就好,之前写的博客,写的不是很好

vue-cli提供了mock的手动支持,在webpack中可配置。

可以专门建个文件夹,里面写模拟的接口数据。
在这里插入图片描述
每个文件名称模拟请求的接口关键词,文件内部举例

function chart(method) {
  let res = null;
  switch (method) {
    case "GET":
      res = [100, 40, 78, 10, 30, 48];
      break;
    default:
      res = null;
  }
  return res;
}

module.exports = chart; //这里不能使用export default xxx; 这种写法

然后在webpack中开启代理拦截,具体详细内容可以看cli和webpack的官方文档

devServer: {
    proxy: {
      "/api": {
        target: "http://localhost:3000",
        bypass: function(req, res) {
          if (req.headers.accept.indexOf("html") !== -1) {
            console.log("Skipping proxy for browser request.");
            return "/index.html";
          } else {
            // 以上内容是从webpack官方文档复制的,下面才是自定义内容
            const name = req.path // 首先拿到axios的请求,解析出地址关键词,对应接口文件名称
              .split("/api/")[1]
              .split("/")
              .join("_");
            const mock = require(`./mock/${name}`); // 引入对应的接口文件
            const result = mock(req.method); // 通过请求方法获取结果的数据
            delete require.cache[require.resolve(`./mock/${name}`)]; // 这里要清除请求缓存,要不在对应接口文件中修改数据,不会动态改变
            return res.send(result); // 将请求的数据发给axios接收
          }
        }
      }
    }
  }

注意:为了防止在联调环境中,还是进行mock请求,所以要作一些配置,在package.json中,配置环境切换

"scripts": {
        "serve": "vue-cli-service serve",
        // "serve:no-mock": "MOCK=none vue-cli-service serve", // 加上这行,在非win环境下,到真正联调环境中,就会不使用mock请求
        "serve:no-mock": "cross-env MOCK=none vue-cli-service serve", // win环境需要添加cross-env插件才能生效

Win环境需要安装:"cross-env": "^5.2.0"

然后再webpack配置中加上对环境的判断

} else if (process.env.MOCK !== "none") { // 这里
            const name = req.path
              .split("/api/")[1]
              .split("/")
              .join("_");
            const mock = require(`./mock/${name}`);
            const result = mock(req.method);
            delete require.cache[require.resolve(`./mock/${name}`)];
            return res.send(result);
          }

重启项目时,就要切换环境了npm run serve:no-mock

个人感想:个人觉得这个方案的缺点是,只能选择一个环境运行程序,也就是说只能mock和真实环境二选一,显然局限性太大了,例如你的工程里有登陆请求接口,那你启动mock环境去调试其他接口时,必定要绕过登陆业务去调试。


easymock

这个配置非常简单,去百度官网,注册一个账户,就可以在里面写模拟接口了(具体怎么写官网有详细的教程)。在官网上配置好后,在你的vue工程中记得要写devServer代理配置,例如:

devServer: {
  // 配置反向代理
  proxy: {
    // 当地址中有/api的时候会触发代理机制
    "/api": {
      // 要代理的服务器地址  这里不用写 api
      target: "https://mock.mengxuegu.com/mock/625c05ab66abf914b1f1bf10/crm",
      changeOrigin: true, // 是否跨域
      pathRewrite: {
        // 去掉api
        "^/api": "/",
      },
    },
  },
  open: true, // 自动打开浏览器
  compress: true, // 启动 gzip 压缩
  hot: true,
},

个人感想:这个方案的好处是配置非常简单,在官网上写好接口路由和内容,而且可以和真实环境上的接口并存,例如上面的配置,开发的时候在需要调试的接口地址加上前缀api即可请求假数据。不过缺点有两个,第一不能进行增删改查,第二公司如果没外网就使用不了。

这个还是很推荐的,个人觉得很好用


Ajax Proxy

这个是个浏览器插件,适合在后端接口部署在真实项目上时的时候使用。使用场景就是,联调时期,后端返回的数据不能满足你展示的调试,你可以直接改后端返回的数据达成你的目的。

具体操作就是,打开插件,新建接口拦截,然后写上要匹配的接口地址(不需要全址,部分即可),然后写上返回的内容,确认,刷新一下浏览器,请求接口即可。
在这里插入图片描述
个人感想:前面也说了,这个方案只适合接口部署后的调试工作,算是一个补充方案吧。

推荐使用


第三方软件

例如:rap、swagger、moco、yapi。

具体的我目前公司都没接触过,感觉都是注重规范的大团队会使用的方案。具体说明在这里就不说了,大家可以百度去了解一下。


json-server

简单体验

首先全局安装:

npm i json-server -g

然后可以在vue的根目录创建用于写接口内容的文件:json-server/db.json:

{
	"name": 123
}

然后启动json-server,会给一个地址给我们,例如localhost:8080

json-server --watch json-server/db.json

然后可以用postman直接请求了,遵循restful Api规范,支持动态增删改查。
例如查询,只需要请求localhost:8080/name,就可以获取到接口返回的数据。

集成在react中

安装依赖:

yarn add json-server -D

根目录下创建__json_server_mock__/db.json,然后在package.json中写入脚本

"json-server": "json-server __json_server_mock__/db.json --watch --port 3001"

然后启动:

npm run json-server

就可以直接使用了。

一些技巧

一、在做查询动作的时候,例如?name=&age=12中name为空,json-server会认为你查的是name为空的,age为12的结果,但其实我们要的是name不做限制,age为12的结果,所以要处理一下这种情况,应该把name直接去掉。

可以借助函数处理:

/**
 * 判断是否是假值
 * @param val
 * @returns
 */
export const isFalsy = (val: unknown) => (val === 0 ? false : !val);
/**
 * 清楚掉对象中值为空的项
 * @param obj
 * @returns
 */
export const cleanObject = (obj: object) => {
  const result = { ...obj };
  Object.keys(obj).forEach(key => {
    // @ts-ignore
    const value = obj[key];
    if (isFalsy(value)) {
      // @ts-ignore
      delete result[key];
    }
  });
  return result;
};

二、如果做查询的时候,需要根据一个对象里具体的属性去做查询,且无法保证所有属性都必定存在时,例如:?name=${obj.name}&age=${obj.age},有可能obj里没有age,所以会出现age=undefined的情况,可以借助node的模块进行解构:

记得先安装qs模块

import { stringify } from 'qs';

// ?${stringify(obj)}

三、通过env的文件去指定开发环境下json-server服务器的请求地址,我觉得比较局限,和真正的开发地址只能二选一,目前我的习惯还是使用devServer针对json-server配一个替换地址。

四、如果相对入参做一些逻辑判断,用db.json的resful规范是做不到的,所以需要自定义接口。新建__json_server_mock__/middleware.js文件,用登陆举例:

module.export = (req, res, next) =>{
  if(req.method==='POST' && req.path==='/login') {
    if(req.body.username === 'admin' && req.body.password === '123456') {
      return res.status(200).json({
        user: {
          token: '123'
        }
      })
    } else {
      return res.status(400).json({
        message: '用户名或密码错误'
      })
    }
  }
  next()
}

然后在去注册这个文件里的所有接口,在package.json中:

"json-server": "json-server __json_server_mock__/db.json --watch --port 3001 --middlewares ./__json_server_mock__/middleware.js"

就可以请求了。


未完待续…


版权声明:本文为pagnzong原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。