利用mock提高效率
利用mock提高效率
谈到mock,就不得不讲前后端分离。理想情况下前后端不分离,由全栈的人以product和infrastructure的维度进行开发,效率是最高的。近些年来业务的复杂度越来越高,真正的全栈人才极为难招,企业只能退而求其次,对开发进行分工细化,让每个人做自己最擅长的事,前端负责UI显示和交互,后端负责业务的逻辑、性能等,从而架构上达到更高的效率。同时由于分工的细化,导致前后端的沟通成本增加,代码的控制权通常在后端,一次小的修改可能导致前后端反复沟通,降低开发效率,就产生了前后端分离的方案。前后端分离通过约定好协议,使用约定的协议进行并行开发,将沟通最后阶段放在联调,节省了大量的时间。
分离的表现主要是视图层的控制交给前端,对于一些偏应用类项目,使用ajax请求,前后端各负责自己的部分,直接达到分离状态,而一些展示类系统,受到seo和用户体验的影响,分离只能达到部分分离,如fis方案。不管是哪种状态的分离,都需要进行协议约定,以达到业务的并行开发。对于前端来说,开发的效果更多依赖于数据,想要最大程度的减少联调时间,就需要根据协议生成数据,这也就是mock的需求。
使用mock开发流程
这里借用yapi的流程图(yapi表示mock服务):
首先,前后端进行定制接口,定制完成后各自进行开发。前端的开发者使用mock数据进行开发,开发完成后进行真实环境的联调,找出开发中的问题,再进行测试、上线等流程。
常用的mock方式
1. 代码层硬编码
直接数据写在代码中(或者独立的文件,代码中手动引入),修改代码跳过接口请求,直接使用数据。这种方式的最大问题是耦合性太强,业务代码中混杂了mock数据,每次正式提交都要保证代码数据指向是正确的,否则会产生神奇的结果。同时不是真正发出网络请求,和真实环境有差异。建议仅在没有其他方式的情况下才使用。
2. 代码中针对使用的ajax库拦截
这种方式分为拦截到本地和拦截到其他服务器。相较于硬编码,拦截式降低了mock数据和业务代码的耦合性,只需要引入拦截的代码,将请求转发至本地,至本地文件或其他服务器。这种方案的主要问题是需要针对代码使用的各种库进行定制插件,初期成本高;同时有部分的代码入侵,需要保证入库代码正确。
拦截至数据文件:
最典型的是Mock.js。这种方式实现了自由编写数据,灵活性比较大,而且mock的数据文件可以同步至仓库中,下次开发时。缺点是同样非网络请求,真实性不足。拦截并改变请求:
这种方式之所以出现是因为服务器的URL和本机的URL规则不同,需要按照规则进行转换。这种方式与真实情况比较接近,同时产生了跨域,需要服务端提供对应的header。
3. 为所有接口统一添加前缀
这种方式在公用文件中直接添加接口前缀,依赖于特定的库功能(或者达到相同效果的代码结构)。同之前的拦截并改变请求类似,但更为简单一些,只改前缀就可以了,同样有代码入侵的问题。
4. 使用其他工具
这种方式分为两种:使用本地或软件数据和代理转发
使用本地或软件数据:
最常用的如:fiddler, charles, whistle等,可以将请求返回指定内容。主要问题是配置比较繁琐,所有操作都在本机,同步困难。代理转发:
这种方式和真实环境极为接近,毕竟纯静态的文件,在服务端也是需要进行代理转发的。可使用的工具就比较多了,使用支持代理转发的开发工具,或者使用上面提到的工具,同样能够将数据转发出去。这种方式最大的优点是:无跨域、能发出真实请求、与业务代码完全隔离。
方案对比
对比以上几种方案,最优的选用代理转发方式,其次是代码拦截方式。拦截至数据文件有个优势就是可以将mock数据和仓库同步,但在不同分支开发时Mock数据可能会冲突。代理转发和拦截至服务器使用最方便,但它需要mockServer。只视开发情况而定。
一些mock用工具
mock的实现非常多,基本上每套完善的前端开发工具都是自带mock的机制。近几年随着nodejs的流行,前端可以非常方便的实现自己的mockServer,所以想列举出所有的还是很困难的,这里介绍一些知名字较高的工具。
1. swagger
- 地址:[https://swagger.io/]
- 介绍: 提到mock,就不得不提到swagger (https://swagger.io/)。它是一个极为流行的一个API设计开发工具,覆盖了从设计到文档到测试部署。它是这样介绍的:
Swagger is the world’s largest framework of API developer tools for the OpenAPI Specification(OAS), enabling development across the entire API lifecycle, from design and documentation, to test and deployment.
在设计RESTFUL类型的API极为有用,它没有专门提供mock服务,但可以提供mock服务的server模板代码,可根据模板自行搭建mock-server。此外,还提供相关的API的JSON结构数据,配合相应的工具来实现类似的效果。
2. Mock.js
- 地址:https://github.com/nuysoft/Mock/tree/refactoring
- 介绍:THX团队出品,本地文件编写mock数据规则,适用于代码库拦截,之前较为流行的一个方案,很多工具都集成了Mockjs语法,目前仓库已经不再更新。
3. rap2
- 地址:https://github.com/thx/rap2-delos
- 介绍:同THX团队出品,是rap0.x的升级版本,使用了nodejs和关系数据库开发,兼容mock.js语法。界面比较简洁,交互友好,支持界面式编辑API。但URL设计与原URL不同,需要使用代码库拦截方式。
4. apiary
- 地址:https://app.apiary.io/
- 介绍:这款在国外用的比较多一些,功能也是比较强大:
Apiary.io平台具有协同设计、即时API模拟、快速生成源码、自动测试和代码调试的开源设计工具,最重要的是可以在线模拟测试,因为该平台具备模拟服务器测试服务,可以把设计好的程序在线测试、验证。
5. easy-mock
- 地址:https://easy-mock.com/
- 介绍:搜车出品,rest api模拟,基于mockjs语法,能够从swagger生成简单数据。
6. yapi
- 地址:http://yapi.qunar.com/getfamiliar.html
- 介绍:这是去哪团队做的,使用了nodejs+mongodb方式开发,主要特性:
- 基于 Json5 和 Mockjs 定义接口返回数据的结构和文档,效率提升多倍
- 扁平化权限设计,即保证了大型企业级项目的管理,又保证了易用性
- 类似 postman 的接口调试
- 自动化测试, 支持对 Response 断言
- MockServer 除支持普通的随机 mock 外,还增加了 Mock 期望功能,根据设置的请求过滤规则,返回期望数据
- 支持 postman, har, swagger 数据导入
- 免费开源,内网部署,信息再也不怕泄露了
rap2和yapi的一些对比
接入mockServer
有了各种极为方便使用的mockServer,想要接入就很简单了。mockServer的一般使用规则:
- URL相同,直接代理转发即可
- URL后半部分相同,直接加上URL前缀即可
- URL规则不同,或需要身份认证,需要拦截转发
拦截式
拦截式针对的是使用一些封装过的ajax库,比如jquery、axios,或者使用fetch库。实现的方式各有不同。如果使用的是支持拦截器模式(如axios),拦截代码就比较简单了,直接在拦截器中改变URL指向即可,指向mockServer或mockjs文件。见以下代码(以下代码是摘自rap或rap2等其他库)。
function wrapAxios(axios) {
var url = ''
var oldRequest = {}
var routePassed = false
axios.interceptors.request.use(function (config) {
url = config.url
config.url = "http://" + ROOT + '/mockjsdata/' + projectId + url;
oldRequest = Object.assign({}, config)
return config;
}, function (error) {
return Promise.reject(error);
});
axios.interceptors.response.use(function (res) {
return res;
}, function (error) {
return Promise.reject(error);
});
}
对于一些不支持拦截器的,或者原生的方法fetch,通过覆盖的方式实现(https://github.com/wenlonghuo/rap2-delos/blob/master/public/libs/fetch.rap.js):
;(function (RAP, fetch) {
if (!fetch) {
console.warn('当前环境不支持 fetch')
return
}
if (!RAP) {
console.warn('请先引入 RAP 插件')
return
}
let next = fetch
let find = (settings) => {
for (let repositoryId in RAP.interfaces) {
for (let itf of RAP.interfaces[repositoryId]) {
if (itf.method.toUpperCase() === settings.method.toUpperCase() && itf.url === settings.url) {
return Object.assign({}, itf, { repositoryId })
}
}
}
}
window.fetch = function (url, settings) {
// ajax(settings)
if (typeof url === 'object') {
settings = Object.assign({ method: 'GET' }, url)
} else {
// ajax(url) ajax(url, settings)
settings = Object.assign({ method: 'GET' }, settings, { url })
}
var match = find(settings)
if (!match) return next.call(window, url, settings)
let redirect = `${RAP.protocol}://${RAP.host}/app/mock/${match.repositoryId}/${match.method}/${match.url}`
settings.credentials = 'include'
settings.method = 'GET'
settings.dataType = 'jsonp'
console.log(`Fetch ${match.method} ${match.url} => ${redirect}`)
return next.call(window, redirect, settings)
}
})(window.RAP, window.fetch)
使用这些插件的方法很简单,直接在html最后添加指向的script标签即可(部分拦截可能需要引入多个标签)。
修改全局URL式
这种情况适合mockServer请求中需要添加baseURL的类型。对于支持baseURL类型的库,设置baseURL即可。如baseURL为:
http://yapi.demo.qunar.com/mock/1304
我们业务代码中请求的api为:
/weather/api
那么我们实际请求的地址是:
http://yapi.demo.qunar.com/mock/1304/weather/api
所以我们应该这么设置(以axios为例):
export default axios = new Axios({
baseURL: process.env.NODE_ENV === 'development' ? 'http://yapi.demo.qunar.com/mock/1304' :
})
如果是不区分环境的情况下,需要在提交前将baseURL设置为空,以免影响仓库代码。
对于不支持baseURL的库,建议封装方法,单独保存baseURL。
代理转发式
代理转发实现的前提是你使用的开发工具支持转发,如果不支持,就需要使用Fiddler、charles等工具进行规则重写。下面举一些例子:
webpack-dev-server中:
proxy: {
"/api": "http://localhost:3000"
}
proxy: {
"/api": {
target: "http://localhost:3000",
changeOrigin: true
}
}
注:changeOrigin是http-proxy设置选项,表示在请求头中将host转换为目标服务器的地址或IP,解决服务器出现请求地址找不到的问题。
nginx(应该没人用吧):
location /api {
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Host $host;
proxy_set_header X-Real-Ip $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
proxy_pass http://localhost:11011;
proxy_redirect off;
}
fiddler中在右侧的tab页中选择autoResponder标签页。编辑rule分别输入
REGEX:^https://server\.example\.com/(.*)
http://www.target.com:3838/$1
mock的一些问题
- mock不能替代联调。尽管mock数据再真实,也无法实现和后端接口一样的逻辑,部分逻辑检查或业务的问题只能联调才能发现。
- mock不能替代测试。mock本身是为了加快开发速度,那些对于代码质量要求比较高的项目,mock服务只能提供一些case。
总结
使用mock前提是前后端有一个明确的接口协议,利用合适的工具才能提高开发效率。强大的mock服务可以使你对开发的代码更为自信,即使没有后端,新手就可以通过mock熟悉之前的业务界面,或者查看一些表现特殊的界面,最大程度减少对后端的依赖。
上面介绍的几款mockServer有几种都是使用nodejs开发的。和其他语言开发的mock服务相比,json格式成为书写的主要格式,虽然用起来容易,但书写上并不方便(json5格式在某种程度上增强了书写体验,但相比yaml等格式还是有所不足)。同时业务情况不同,针对性的选择不同的平台,推荐使用rap2和yapi,前者界面更为简洁,操作方便,后者功能更为强大。如果有特殊的需要,可以自己写一个,顺便练练手。
搭建一个属于自己的server
参考
【你是如何构建 Web 前端 Mock Server 的? - 莫池宇的回答 - 知乎
https://www.zhihu.com/question/35436669/answer/235608128】
利用mock提高效率的更多相关文章
- Java之利用Freemarker模板引擎实现代码生成器,提高效率
https://blog.csdn.net/huangwenyi1010/article/details/71249258 java模板引擎freemarker代码生成器 更多 个人分类: 一步一步 ...
- [.net 面向对象程序设计进阶] (17) 多线程(Multithreading)(二) 利用多线程提高程序性能(中)
[.net 面向对象程序设计进阶] (17) 多线程(Multithreading)(二) 利用多线程提高程序性能(中) 本节要点: 上节介绍了多线程的基本使用方法和基本应用示例,本节深入介绍.NET ...
- [.net 面向对象程序设计进阶] (16) 多线程(Multithreading)(一) 利用多线程提高程序性能(上)
[.net 面向对象程序设计进阶] (16) 多线程(Multithreading)(一) 利用多线程提高程序性能(上) 本节导读: 随着硬件和网络的高速发展,为多线程(Multithreading) ...
- 计算机天才Aaron Swartz 名作 《如何提高效率》——纪念真正的“hacker"!
如何提高效率 <HOWTO: Be more productive>(如何提高效率)作者:Aaron Swartz 肯定有人跟你说过这样的话,“你有看电视的那么长时间,都可以用来写一本书了 ...
- 让你提高效率的 Linux 技巧
想要在 Linux 命令行工作中提高效率,你需要使用一些技巧. 巧妙的 Linux 命令行技巧能让你节省时间.避免出错,还能让你记住和复用各种复杂的命令,专注在需要做的事情本身,而不是你要怎么做.以下 ...
- 提高效率的Linux命令
提高效率的Linux命令 一.fc 二.disown 三.Ctrl + x +e 四.!! 两个感叹号 五.一次创建多个目录或文件 六.tee 七.删除从开头到光标处的命令文本 八.删除从光标到结尾处 ...
- 批处理文件 .bat 并行Arcpy脚本提高效率的思路-提升版
目录 前言 Arcpy脚本 导入库 函数定义 循环实现 批处理(.bat)脚本 前言 我在之前的博客园博客里,阐述了如何编写Arcpy脚本,如何利用Windows bat批处理脚本同时打开多个cmd窗 ...
- [.net 面向对象程序设计进阶] (18) 多线程(Multithreading)(三) 利用多线程提高程序性能(下)
[.net 面向对象程序设计进阶] (18) 多线程(Multithreading)(二) 利用多线程提高程序性能(下) 本节导读: 上节说了线程同步中使用线程锁和线程通知的方式来处理资源共享问题,这 ...
- Oracle多表连接,提高效率,性能优化 (转)
执行路径:ORACLE的这个功能大大地提高了SQL的执行性能并节省了内存的使用:我们发现,单表数据的统计比多表统计的速度完全是两个概念.单表统计可能只要0.02秒,但是2张表联合统计就可能要几十表了. ...
随机推荐
- mysql 中order by 与group by的顺序
mysql 中order by 与group by的顺序 是: select from where group by order by 注意:group by 比order by先执行,order b ...
- 【good】在CentOS 6.x上安装GlusterFS
转发:http://quenywell.com/install-glusterfs-on-centos-6-x/ 本文主要介绍如何在CentOS 6.x上快速安装GlusterFS.GlusterFS ...
- Linux网络设备驱动架构
Linux网络设备驱动程序体系结构分为四层:网络协议接口层.网络设备接口层.提供实际功能的设备驱动层以及网络设备与媒介层. (1)网络协议接口层向网络层协议提供统一的数据包收发接口,不论上层协议是AR ...
- scrapy_创建_调试
如何创建scrapy项目? 输入命令: scrapy startproject project_name 在当前目录下创建名字叫project_name的scrapy项目 命令格式:scrapy st ...
- 前端开发人员需要了解的CSS原理
转自http://web.jobbole.com/10011/ 一.浏览器的发展与CSS 网页浏览器主要通过HTTP协议连接网页服务器而取得网页,HTTP容许网页浏览器送交资料到网页服务器并且获取网页 ...
- discuz数据库相关表
discuz 数据表对照cdb_access 用户权限表 cdb_adminactions 管理动作表cdb_admingroups ...
- android 自定义控件用的定时CountDownTimer
定时执行在一段时候后停止的倒计时,在倒计时执行过程中会在固定间隔时间得到通知(译者:触发onTick方法), 下面的例子显示在一个文本框中显示一个30s倒计时: new CountdownTimer( ...
- SEO—Meta标签优化
Meta标签之一"标题": 标题是网站中很重要的一个标签,他在搜索引擎中是直接显示出来的,一般情况下要网站的核心关键词和网站名称都写进去,这样更有利于网站的排名.但是要注意标题的长 ...
- NetworkManager 冲突
今天看centos7的视频的时候发现视频里总是配置ip失败,明明什么都对的,没有错误 至少在逻辑上是没有的 情况发生 1.centos7会自动启动这个服务,NetworkManager服务,重启后ip ...
- 【转】shell中如何判断一个变量是否为空
判断一个脚本中的变量是否为空,我写了一个这样的shell脚本: #!/bin/sh #filename: test.sh para1= if [ ! -n $para1 ]; then echo &q ...