一个简单的 mock 工具应该长什么样


为了提升前后端协作开发效率,一个称手的 mock 工具很重要,结合本人这近半年开发 moky 的经历,说点浅显的心得和体会。正如其名 moky = mock + proxy,因为我觉得 mock 和 proxy 已经可以覆盖 80% 的场景,所谓二八原则,剩下 20% 功能会牺牲工具本身简洁性和性能。下面结合场景来看看 mock 工具的设计思路以及我认为的该有的样子。

场景

我们假设现在要做一个网站应用,包括后端和前端(虽然也有 BaaS 和纯静态等方案),继续假设前后端不是同一个人开发。前端视角看整个项目结构如下:

场景

上部分是客户端,下部分是服务端,两者交互的数据大致分为:HTML 页面、异步接口和其它静态文件三部分。从开发分工来划分的话,紫色部分是后端工作(业务逻辑、增删查改、页面和异步接口路由……),黄色部分是前端工作(模板逻辑、脚本、样式等)。

特别注意,如果是 React/Angular/Vue/… 等 MV* 框架构建的单页应用,这里的模板不是一般意义的模板引擎的模板了,仅仅是一个入口 HTML 页面,后端页面路由逻辑也省了,因为只有一个入口页。所以把 SPA 跟使用传统模板引擎构建的应用 放在一起讨论并不会影响逻辑,如果有特别注意的会额外提到。

Mock

好了,前后端已经协商好交互的接口了,各自开发了。但是大家总感觉哪里不对劲,特别是前端同学,因为前端需要边看效果边写,此时后端也才刚刚开始,如果做到没有后端支持的情况下前端也可以顺利写好页面?

再看一眼上面的图,说白了就是前端如何本地模拟 Controller 层的页面渲染+路由异步接口路由静态文件路由,这两个抽离出来其实都是数据,这里提炼下关键词:数据渲染路由

  • 数据:这里数据大多数情况是 JSON 格式,因此可以直接本地新建符合要求的 JSON 文件即可(分为页面的和异步接口的),这就是常说的 mock 数据
  • 路由:这个实现就比较简单了,本地启一个简单的 Server 即可,一般这里框架路由支持都是非常简单的
  • 渲染:页面的渲染的过程可以使用公式 模板引擎(模板, 数据) 简单表示,现在就差模板引擎了,而这个一般都是现成的

以上叙述来看,貌似实现一个 mock server 还是比较简单的,实际操作中还是可能遇到一些挫折的,比如:数据不是 JSON 的情况、路由顺序以及错误处理、模板引擎对环境的依赖(eg: freemarker 依赖 JAVA),细节不多累述,看下面加了 mock 后的结构:

Mock

其实就是把之前的 Controller 又“实现”了一遍,然后数据改为从本地 mock 文件里取,模板文件和静态文件也是用的本地的。

Proxy

过了好多天了,前后端都开发的差多了,接下来就是传说中的联调阶段了。即使之前很明确的定义好了接口和交互的数据格式,但是之前难免有疏漏,需求也可能中途调整过,所以联调很多时候花的时间并不比开发阶段少多少。

来看看我们原始联调方式,前端发现问题,前端修改了代码推送到仓库,后端拉取代码部署调试,发现还有问题,继续上述步骤……这个时间花费甚至可能占到联调时间一半!

从始至终,我一直有意无意的强调一个思想:前后端交互关键就是数据层面的交互,从数据视角出发,联调阶段其实仅仅把假的 mock 数据换成真的数据而已!这样的话,在 mock server 基础上实现 proxy 就显得非常简单,仅仅把 Mock 模块换成 Proxy即可,最终的结构呈现如下:

Proxy

proxy 会从后端的反向代理得到正常数据,再交给 mock server 按原来 mock 方式处理。这样还没完,仔细看上图会发现后端渲染那部分被干掉了,取而代之的是直接返回渲染之前的原始数据,因为只有这样 mock 和 proxy 模式才可以无痛切换。

总结

  • mock + proxy 基本可以覆盖从开发到联调阶段大部分行为,当然因为应用本身多样性,仅仅用 mock + proxy 有时候也会有不便利的地方,那就结合其它工具吧;
  • 最后一段里的“后端渲染那部分被干掉了”,这句话虽然轻描淡写,实际搞起来还是比较烦的,因为这跟语言和框架是相关的,四个月前我就曾问过很多人关于 Spring MVC 如何设置,很久都没得到答案,后面居然发现有同学通过拦截器的方式实现了,而且完全符合我的预期;
  • 文中也有地方说了,SPA 应用和模板引擎构建的应用是不一样的,但也仅仅少了页面的 mock 和 proxy 的步骤;
  • 最后,有兴趣的话可以试试 moky,有建议或意见可以提 Issues :-)