手记

前端工程化之--Mock解决方案

图片来自网络

前端Mock的常见解决方案

Mock数据进行调试是前端构建中不可或缺的一步,常见的前端Mock方案分为4种:

  1. 在代码层硬编码
    比如有一个函数负责请求某个接口,获得的回返数据,并对该回返数据进行操作。那么可以通过硬编码的方式,直接定义一个数据变量在代码中,该变量保存了回返的Mock数据。这种Mock方法操作比较简单,但缺点也很明显,就是Mock更改了代码逻辑,和代码耦合性太强。而且并不能模拟真实的网络请求的过程,局限性强,覆盖面窄。

  2. 在前端JS中拦截
    典型的解决方案就是Mock.js,通过在业务代码前挂载该JS文件,就可以无痛拦截Ajax请求。这种Mock方式相较于硬编码,虽然实现了Mock与代码的部分解耦,但无法完全和业务代码解耦(因为必须挂载一个JS并进行Mock配置)。虽然提供了大量的Mock API,但是也仍然无法发出真实的网络请求,模拟真实度不够。另外这种方式还存在一些不足,因为是对XHR对象的改写,有些情况下兼容性并不好,比如IE8等低版本浏览器,还有较新的Fetch API也拦截不到。

  3. 代理软件(Fiddler、Charles)拦截
    Fiddler和Charles可以对网络请求进行拦截,将其替换为我们需要的Mock数据,这也不失为一种Mock方式。其优点主要是真实性强,但这种方式操作步骤比较繁琐,不方便统一配置,Mock成本较高。

  4. Mock-Server
    最合适的方案无外乎搭建独立的Mock-Server,开发的前期阶段,所有的接口都会指向该Mock-Server。因为可能存在跨域的情况,所以一般都需要在开发环境搭配一套接口代理做搭配。这种方案对业务代码完全不具有侵入性,并且通用性强。缺点也很明显,成本高(还需要另起一个Mock-Server服务,并对其进行管理)。

接口定义与Mock数据相结合的方案

其实常见的解决方案便是上面提到的几种,或是在这类的基础上进行调整,但整体思路基本一致。Mock的本质是为了能让接口消费者脱离接口生产者进行开发,但是这个脱离并不是指脱离生产者的接口定义随意开发,接口定义与Mock数据的一致性也是我们必须考虑的一个问题,我们必须要确保Mock出的数据符合接口定义中的要求。所以实际上我们还需要多考虑一个问题:如何让接口定义的维护和Mock结合起来?

很庆幸的是,我们有RAP这项工具。RAP是一款非常棒的工具,它是一个可视化接口管理工具,将所有的接口开发定义以其要求的格式进行管理,并能根据这些定义来产生Mock数据,提供给消费者。

既然有了RAP为我们提供Mock-Server服务,那么我们下一步欠缺的就是如何让代码中的网络请求能直接访问到RAP上。RAP有提供一种插件JS,是在Mock.js的基础上扩展的,可以拦截页面上的请求,但暂时仅支持Kissy和jQuery。为此我们在Koa的基础上,结合RAP提供的NodeJS插件(rap-node-plugin)开发了一组工具,能够将配置中要求拦截的所有请求转发到RAP上,并将RAP生成的数据返回给请求方。另外,考虑到Mock调试中,RAP的Mock规则有限和接口定义文档频繁变更的问题,我们还加入了本地mock解决方案,可以随时随地的更改本地local-mock.js文件,避免频繁的RAP文档编辑。本地mock还支持以函数的形式动态返还Mock数据,大大提升了Mock数据生成的能力。另外,在网络请求Mock中,网络延时有时必不可少,我们通过在接口定义中添加_delay字段,可以决定让该接口多长时间后返回,其它下划线字段可以按需添加。RAP中的配置:

RAP接口配置

Mock方案实现

方案主要由以下4个组件构成:

mock工具

  • config.js
    包含一些对mock工具的配置

/**
 * 默认配置
 */export default {  PATH: '/pc/*',  // 默认拦截的路径
  USE_RAP: true, // 默认为true,会去寻找并调用RAP上的接口
  RAP_CONFIG: {    host: 'rap.fe.yeshj.com', //启动的服务主机
    port: 80, //端口号
    projectId: 115, //RAP配置的项目ID
    mock: '/mockjsdata/', //RAP前缀
    wrapper: '' //不需要包装
  }
}
  • filter.js
    KOA中间件,会对config中配置的PATH进行请求拦截,并根据相关配置获得请求回返数据,进行一定程度的包装,回返为Mock数据。与接口相关的_delay操作也在该中间件内实现

  • local_mock.js
    负责本地mock规则及数据的存放。_delay关键字在此配置,header支持自定义回返头部,body回返体数据支持以函数的形式进行生成。

module.exports = {  "POST /pc/check": {    "_delay": 1000,    "header": {      "Content-Type": "application/json;charset=utf-8"
    },    "body": function (ctx) {      return {        "status": 0,        "data": {          "ctx": ctx
        }
      }
    }
  },  "POST /pc/info": {    "_delay": 0,    "header": {      "Content-Type": "application/json;charset=utf-8"
    },    "body": {      "data": {        "id": "12121212"
      },      "message": "成功",      "status": 0
    }
  }
}
  • rap_connector.js
    该组件是对rap-node-plugin的封装,方便调用。

开发环境集成

下面就是如何将mock集成到我们的开发环境中去了。

  • 建立mock目录
    该Mock方案因为涉及到配置的调整和本地Mock数据的改写,不适于做成单独的node_module进行封装,所以我们选择将mock方案集成到项目中的构建工具中去,目录层级如下:

Paste_Image.png

  • package.json中增加新脚本mock:

"scripts": {    "start": "npm run mock",    "mock": "babel-node ./tools/build/server.js --dev --mock"}
  • 在koa中注入mock中间件:

if (argv.mock && config.mockEnable) {    let mockFilter = require('../mock/filter.js');
    app.use(mockFilter());
}

最后一步的工作很简单,就是在mock/config.js中进行一些简单配置,然后在bash中输入npm start就可以享受我们整套的mock解决方案了。



作者:可木Changer
链接:https://www.jianshu.com/p/720b12b5d120


0人推荐
随时随地看视频
慕课网APP