题目有点大,下面简单说下要解决的问题以及对应的解决方案思路。
问题
mock也是前端工程化的一部分,所以正常来讲每个前端项目都会有各自mock 的实现。
一般前端实现mock,有不限于以下几种形式:
- 手写假数据,接口请求直接返回写好的假数据;
mock.js拦截接口,并返回对应编写好的mock;easymock、yapi等平台接管;Json-server拦截+faker生成mock;- ......
以上方式各有优缺点,场景不同,需求也不一样,存在即合理,不必强分好坏。
但根据个人调研使用,无论使用哪一种,都免不了诸如以下:
- 接口、参数的复制粘贴
- mock数据大多只支持查询
等通用性问题,当然也可能是因为使用不够深入的原因。所以基于这些问题,就想着能不能把这种通用性问题通过工具去解决呢?
所以就有了本篇内容的实践。
实现步骤
大概捋一下思路:
swagger-json生成接口、配置信息;json-server接管并处理对应请求;faker根据1的接口配置信息,处理mock数据;- 整合
2和3步骤,校验mock的增删改查功能; - 客户端校验;
看步骤可知,和通常mock方式不一的,核心是多了第一个步骤,动态生成全系统接口及相关出入参配置信息,以及多种方式的整合处理。
过程工作量会比较大,实现过程也不一定相同,但原理是一样的,所以本篇内容偏理论,下面仅讨论实现原理。
1. 接口配置
实现接口mock的过程,通常这部分工作的重复量是最大的,就是手动的复制接口及出入参,然后针对的处理mock。
所以基于这种情况,之前实现了通过类似swagger等平台,一键获取接口及出入参配置的功能。
可看 swagger-json 通过swagger接口快速生成AntDesign组件配置。
简单讲下swagger-json的实现原理:
- 根据后端提供的swagger-ui地址,获取渲染swagger-ui的接口;
- node环境请求接口,解析对应的接口及出入参数据结构;
- 按需组装出入参,生成对应需要的出入参配置;
- 生成对应json文件,方便一键取用,大量减少一个个复制粘贴的工作;
实现过程的重点是swagger接口的数据解析,以及按需数据的组装,剩下的就是文件的读写。
实现之后基本随处可用,根据不同需求,改改出入口模型就行,收益比例比较高。
贴一个生成的简单例子
/**
接口:get-people-list
生成文件:get-people-list.json
生成配置如下:
*/
{
"query": [
{
"key": "name",
"label": "查询人",
"children": []
},
{
"key": "age",
"label": "查询年龄",
"children": []
},
{
"key": "tel",
"label": "查询电话",
"children": []
}
],
"params": [
{
"key": "name",
"label": "姓名",
"children": []
},
{
"key": "age",
"label": "年龄",
"children": []
}
]
}
根据上面的json,可以很方便的接入如Antd的表单及table等组件的config部分,省去手动配置的过程。
2. 请求接管
上面生成了对应的接口及配置,接下来处理请求接管的部分。
mock.js等也可以接管请求,但使用json-server更好的地方,在于json-server实现并增强了db、server的处理,基本达到仿真db的能力。
下面是处理过程:
-
根据json-server读写规则,同步、修改上面生成的接口及配置;
根据接口的特性,请求路径及req、res等一般都需要做rewrite才能满足需求,而json-server的匹配规则个人感觉有点绕且不是很清晰。
但这部分是请求接管的核心,不能省略。
因为是一次性处理整个对接系统的接口,所以接口越多工作量和复杂度相对也越大一些。
贴个简单的rewriter例子:
{ //重写 /app/路径 "/app/*": "/", // post请求接口 /get/list/1,json-server实际会对文件get-list.json发起get-list且id为1的请求,最终返回id=1的数据 "POST/get/:people/:id": "GET/app-:people/:id", }规则比较简单,所以也只满足了基本需求。
-
启动server,接口调试;
参考上面的接入,可以拿几个简单的接口,做下匹配及转译,然后启动server,先做查询、新增的调试,成功之后实现批量操作。
参考 simple-example。
-
整合接口list,json监听;
单个接口调试完成了增删改查流程,基本规则也就摸的差不多清楚,接下来整合接口。
需要整合的原因是当json文件过多的时候,json-server监听无法达到预期,原因也没有深究,所以干脆做了整合,只监听一个文件。
这个时候如果想调试大量的接口,就需要不停复制粘贴相关接口及出入参,效率极其低下,这时候就体现了上面
swagger-json实现的好处了。下面简单看下实现后的贴图
-
按需调试,磨平差异
接口量大,不一定每个接口的情况都能兼顾到,这个时候需要根据不同情况,做不同的接口rewrite及req、res的拦截转换处理。
其实如果后端接口实现足够规范,前面
1~3基本能满足需求,但事实总是不能如人意,所以这步往往没法省略。json-server也考虑到这点,提供了不同情况的处理,下面是部分规则截图
-
拓展处理
假设
json-server仍然无法满足对拦截处理的需求,可以考虑手动接入更符合日常使用的express等作拓展处理。
3. faker数据
前面调通了json-server的拦截,简单实现了接口对应的增删改查功能,但对查询而言,往往需要大量数据的mock。
对大量数据的生成,这里用的是faker-js+lodash实现。
原理就是lodash负责化量,faker负责生成。
下面贴个简单demo:
import { faker } from "@faker-js/faker"
import { times } from "lodash-es"
// db数据faker
export function fakerDb (params /** 出参 */ = {}, length/** mock数据长度 */ = 20) {
const mock = times(length, function (n) {
const obj = {}
const keys = Object.keys(params)
for (const key of keys) {
obj[key] = faker.name.fullName()
}
return {
...obj,
id: n + 1
}
})
return mock
}
再结合上面的接口接管及整合,就能够生成仿真mock。
下面看下整合后每个接口faker20条数据的mock情况
4. 客户端校验
上面其实已经基本实现了mock平台的功能,接下来就是在dev等环境实现接口的真实mock。
和常规流程一样:
- 启动上面
mock-server,比如启动后地址是localhost:3000; - 真实请求把
proxy及baseUrl换成mock的地址及对应配置; - 发起请求;
下面看下真实环境的演示过程:
-
发起请求
// Get默认是查询功能,Post是新增 axios.get("http://localhost:3000/app/matter/detail").then(res => { console.log('Mock:', res); }) axios.post("http://localhost:3000/app/matter/detail").then(res => { console.log('Mock:', res); }) -
控制台验证
-
mock文件验证
可以看到chrome控制台及本地接口整合并接入faker后的mock/index.json都生成了对应数据,这也是使用faker替代mockjs的原因,可以更真实的反馈fake-db情况。
总结
上面只是讲了实现的基本原理及过程,具体实现过程的工作量还是相对大一些,也就不再细述,下面再次总结下过程:
- 通过swagger接口获取组装并生成接口配置的json文件;
- json-server拦截请求做转发处理;
- faker生成db数据;
- 发起proxy请求验证;
还是上面的话,前端mock有多种多样的实现方案,这里也只是针对自身情况,对已有的功能做整合,但不管如何实现,需求其实都是一致的。
这个最终的需求就是赋能增效,这也是程序员工作本身永恒的主旋律,只要能更好的实现需求,方法本身也只是某个阶段的某个恰好的方法而已。
所以程序员实现需求只是基本要求,能够更好的、创新性的实现,才是推动技术发展的重要能力。