前端独立交付需求背景下的Mock数据多方案解读

作者 | Iven 爱数AnyBackup灾备管理研发部-中级前端开发工程师

      在前后端分离的趋势下,前端开发逐步减少对后端的依赖,甚至可以不与后端进行联调,独立交付需求。在这样的背景下,首先要解决的就是接口数据的Mock,根据服务端约定好的接口进行数据Mock,同时修改数据来满足不同的开发场景。

一、请求流程介绍

      首先来分析下开发环境下请求的整个流程:


      发送请求流程:

      1. 操作页面时首先会经过编译后的源码,按照源码的逻辑进行请求封装,再发送请求

      2. 请求通过浏览器向目标地址发送请求,开发环境下目标地址为编译工具提供的前端服务器地址

      3. 编译工具接收到请求后,根据配置项对请求处理,处理完成后向后端服务器发送请求


      响应请求流程:

      1. 后端服务器接收请求后,匹配到对应的路由进行逻辑处理,并将结果返回

      2. 编译工具拿到结果,根据配置项内容进行处理,向浏览器返回处理后的结果

      3. 浏览器接收数据后,按照源码逻辑处理数据,将新的数据呈现在页面上

二、Mock解决方案

      按照请求在本地和服务器两端控制,我们将Mock方式分为本地Mock服务器Mock


      根据上述请求的整个流程,前端Mock数据的解决方案可以大致分为以下几种:

      1. 本地Mock

          1.1 逻辑嵌入

          1.2 源码请求拦截

          1.3 浏览器请求拦截

          1.4 代理封装

      2. 服务器Mock

          2.1 服务化

          2.2 代理拦截

          2.3 服务拦截

      我们以渲染一个列表为例,使用Axios获取接口数据:

// userlist.js 文件
import axios from 'axios'
const getUserList = async () => {
const users = await axios.get('/user/list')
   return users.data.responseData
}

三、Mock方案实践

    一. 本地Mock

          方式一:逻辑嵌入

          最简单一个方式就是将数据直接返回,不发送请求。

// mock.js
export default users = {
    status: 200,
    data: {
        responseData: [{
            name: 'user1'
        }],
        err: null
    }
}

// userlist.js 文件
import axios from 'axios'
import usersData from 'mock.js'
const getUserList = async () => {
    // const users = await axios.get('/user/list')
    const users = usersData
    return users.data.responseData
}

          结论:

              优点: 前端控制接口数据,不必通过后端增删改来修改返回数据;

              缺点: 这种方式侵入到了代码中,开发和后期维护肯定是极其不友好的;


          方式二:源码请求拦截

          使用中间件,统一在中间件做处理,axios提供了拦截器,可以在响应的拦截器中做统一的处理。

          (不只是axios,其他的请求工具也都提供了拦截器的功能,这里主要说明解决方案)

// axiosConfig.js配置文件
import usersData from 'mock.js'
import axios from 'axios'
axios.interceptors.response.use((response) => {
    if (response.request.url === '/user/list') {
        return usersData;
    } 
    return response
}, (error) => {
    return Promise.reject(error);
});
export default axios

// userlist.js 文件
import axios from 'axiosConfig'
const getUserList = async () => {
    const users = await axios.get('/user/list')
    return users.data.responseData
}

          结论:

              优点: 这种方式与上一个相比,统一在一个文件内管理,减少了对业务代码的侵入;

              缺点: 同样的还是有代码的侵入;


          方式三:浏览器请求拦截

          拦截请求,请求直接在浏览器里返回结果,使用Service Worker对请求进行出来,返回自定义结果。比如 Mock Service Work工具

import { rest, setupWorker } from 'msw'
import userData from 'mock.js'

const handlers = [
    rest.get('/user', () => {
        return res(
            ctx.status(200),
            ctx.json(userData)
        )
    })
]

const worker = setupWorker(...handlers)
if (process.env.NODE_ENV === 'development') {
    worker.start()
}

          结论:

              优点:统一在一个文件内管理,较少对代码的侵入;

              缺点:在项目内还是会有侵入,数据修改不灵活;


          方式四:代理封装

          使用打包工具的本地服务功能转发请求,在开发环境下,都会起一个服务,用于本地访问查看页面,基于这个流程,可以在服务上做一些处理。

           以webpack工具为例,在代理配置中添加路由,并在该路由下修改返回对象。

// webpack.dev.js
module.exports = {
    //...
    devServer: {
        proxy: {
            '/user': {
                target: 'http://localhost:3000',
                bypass: function (req, res, proxyOptions) {
                    // 需要转换 mock.js 为 json文件,webpack在node环境下不支持import方式
                    let jsonPath = path.resolve(__dirname, 'mock.json')
                    res.status(200).send( JSON.parse( fs.readFileSync(jsonPath) ) )
                }
            }
        }
    }
};

以webpack工具为例,在代理配置中添加路由,并在该路由下修改返回对象。

          结论:

                优点:使用代理转发的方式,无代码侵入,一种全新的思路,是质的提升;

               缺点:需要在本地生成多个json文件,统一个接口,增删改查都需要配置不同的json文件;

    二. 服务器Mock

          继上面本地转发的方案后,可以将json文件抽离到项目之外,开启一个服务器将json暴露出去,由本地转发替换为转发到服务器上。

          基于这样的方案,可以使用数据库进行存储代替json文件,越来越多的Mock平台出现了,比如 大搜车的easymock、阿里的 rap2、去哪儿网的 Yapi平台等等,Yapi接口管理工具不只是前端工具,也集成了测试方案,是很优秀的工具。

          方式一:服务化

          打包工具转发,通过配置代理地址,直接请求到平台的接口。

          首先在平台上注册账户并添加自己的接口,然后在代理中配置地址。

           (以webpack工具为例,在代理配置中添加路由,配置该路由的转发地址。)

// webpack.dev.js
module.exports = {
    //...
    devServer: {
        proxy: {
            '/user': {
                target: 'http://xxx.xxx.com/xxx' // 根据平台地址填写
            }
        }
    }
};

          结论:

              优点:接口数据可在平台实时修改,项目无其他非相关的代码;

             缺点:每次接口修改,都需要重启服务,修改成本较高;


          方式二:代理拦截

              使用代理服务器进行转发,脱离对框架的依赖。在打包工具访问平台的网络链路流程中,添加一个代理服务器,控制代理服务器从而控制API转发流程。

               (以nginx工具为例,配置不同路由对应的服务器。)

# nginx.conf
http {
    include mime.types;
    default_type application/octet-stream;
    sendfile on;
    server {
        listen 8081;
        server_name 127.0.0.1;
        root D:/worksapce/project; 
        location /user {
            # 根据平台地址填写
            proxy_pass http://xxx.xxx.com/xxx;
        }
    }
}
// webpack.dev.js
module.exports = {
    //...
    devServer: {
        proxy: {
            '/user': {
                target: 'http://127.0.0.1:8081'
            }
        }
    }
};

          结论:

              优点:接口在代理服务器控制,可随时切换Mock平台,API地址,解决跨域等问题,不必重启打包工具;

             缺点:需要安装学习nginx工具,在临时处理问题等一些特殊场景下成本较高;


          方式三:服务拦截

              使用后端服务转发,后端服务不仅可以开发前端接口,返回需要的数据外,还可以进行路由转发,返回对应服务器的接口数据。

// proxy.js 文件
const http = require('http')
const httpProxy = require('http-proxy')
// 创建一个代理服务
const proxy = httpProxy.createProxyServer();
//创建http服务器并监听8888端口
let server = http.createServer(function (req, res) {
    let url = req.url
    if (url.indexOf('/user') >-1) {
        //将用户的请求转发到本地9999端口上
        proxy.web(req, res, () => {
            return {
                target: 'http://xxx.xxx.com/xxx;', // 根据平台地址填写
            }
        });
        //监听代理服务错误
        proxy.on('error', function (err) {
            console.log(err);
        });
    }
});
server.listen(8081, '0.0.0.0');

// webpack.dev.js
module.exports = {
    //...
    devServer: {
        proxy: {
            '/user': {
                target: 'http://127.0.0.1:8081'
            }
        }
    }
};

          结论:

             优点:快速搭建代理服务,前端友好的Node环境可减低开发难度,代理服务重启成本低;

             缺点:需要多启动一个代理服务进行转发;

四、Mock方案总结

          本篇文章主要是对Mock数据方案的归纳整理,列举了简要的操作步骤,详细步骤可自行查找相关资料。

            结合上面的解决方案,可以根据场景的需要选择不同的方案:

            1. 临时页面修改,可通过代码侵入的方式快速解决;

            2. 对应新的项目,可以使用代理服务的方式规范开发;

            3. 处理多个项目时,可以通过nginx配置多个端口来降低服务重启的成本。

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值