zoukankan      html  css  js  c++  java
  • 利用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

    Apiary.io平台具有协同设计、即时API模拟、快速生成源码、自动测试和代码调试的开源设计工具,最重要的是可以在线模拟测试,因为该平台具备模拟服务器测试服务,可以把设计好的程序在线测试、验证。

    5. easy-mock

    • 地址:https://easy-mock.com/
    • 介绍:搜车出品,rest api模拟,基于mockjs语法,能够从swagger生成简单数据。

    6. yapi

    • 基于 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】

  • 相关阅读:
    Nginx核心配置-作为上传服务器配置
    Nginx核心配置-作为下载服务器配置
    Nginx核心配置-长连接配置
    Nginx核心配置-检测文件是否存在
    Nginx核心配置-自定义日志路径及清空日志注意事项
    Nginx核心配置-自定义错误页面
    Nginx核心配置-location的登录账户认证实战篇
    Nginx核心配置-location的匹配案例实战篇
    前后端分离-Restful最佳实践
    Django模板技术
  • 原文地址:https://www.cnblogs.com/dreamless/p/8487322.html
Copyright © 2011-2022 走看看