在前后端分离的趋势下,前端不断摆脱对后端的依赖,甚至前端可以独立交付需求,不必等待与后端的联调。实现这种目标首先要解决的就是接口数据的 Mock,由前端自身准备数据,更新数据来满足不同的开发场景。
一、请求流程介绍
首先来分析下开发环境下请求的整个流程:
发送请求流程:
1. 操作页面时首先会经过编译后的源码,按照源码的逻辑进行请求封装,再发送请求
2. 请求通过浏览器向目标地址发送请求,开发环境下目标地址为编译工具提供的前端服务器地址
3. 编译工具接收到请求后,根据配置项对请求处理,处理完成后向后端服务器发送请求
响应请求流程:
1. 后端服务器接收请求后,匹配到对应的路由进行逻辑处理,并将结果返回
2. 编译工具拿到结果,根据配置项内容进行处理,向浏览器返回处理后的结果
3. 浏览器接收数据后,按照源码逻辑处理数据,将新的数据呈现在页面上
二、Mock 解决方案
根据上述请求的整个流程,前端 Mock 数据的解决方案可以大致分为以下几种:
1. 本地 Mock
* 代码逻辑修改
* 本地转发
2. 服务器 Mock
* 编译工具转发
* 代理工具 nginx 转发
* node 服务转发
我们以渲染一个列表为例,使用 Axios 获取接口数据:
// userlist.js 文件
import axios from 'axios'
const getUserList = async () => {
const users = await axios.get('/user/list')
return users.data.responseData
}
复制代码
a) 本地 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
}
复制代码
结论:
优点: 这种方式与上一个相比,统一在一个文件内管理,减少了对业务代码的侵入
缺点: 同样的还是有代码的侵入
方式三:使用打包工具的本地服务功能转发请求
在开发环境下,都会起一个服务,用于本地访问查看页面,基于这个流程,可以在服务上做一些处理。
以 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) ) )
}
},
},
},
};
复制代码
优点:使用代理转发的方式,无代码侵入,一种全新的思路,是质的提升
缺点:需要在本地生成多个 json 文件,统一个接口,增删改查都需要配置不同的 json 文件
b) 服务器 Mock
继上面本地转发的方案后,可以将 json 文件抽离到项目之外,开启一个服务器将 json 暴露出去,由本地转发替换为转发到服务器上。
基于这样的方案,越来越多的 Mock 平台出现了,比如 大搜车的 easymock、阿里的 rap2、去哪儿网的 Yapi 平台等等,Yapi 接口管理工具不只是前端工具,也集成了测试方案,是很优秀的工具。
方式一:打包工具转发,通过配置代理地址,直接请求到平台的接口
首先在平台上注册账户并添加自己的接口,然后在代理中配置地址
以 webpack 工具为例,在代理配置中添加路由,配置该路由的转发地址。
// webpack.dev.js
module.exports = {
//...
devServer: {
proxy: {
'/user': {
target: 'http://xxx.xxx.com/xxx' // 根据平台地址填写
}
},
},
};
复制代码
优点:接口数据可在平台实时修改,项目无其他非相关的代码
缺点:每次接口修改,都需要重启服务,修改成本较高
方式二:使用 nginx 进行转发,脱离对框架的依赖
在打包工具访问平台的网络链路流程中,添加一个代理服务器,控制代理服务器从而控制 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 工具,在临时处理问题等一些特殊场景下成本较高
方式三:使用后端服务转发
后端服务不仅可以开发前端接口,返回需要的数据外,还可以进行路由转发,返回对应服务器的接口数据。
这里以 Node 作为代理服务进行转发为例。
// 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 数据方案的归纳整理,列举了具体的操作步骤,详细步骤可自行查找相关资料不中。
结合上面的解决方案,可以根据场景的需要选择不同的方案:
1. 临时页面修改,可通过代码侵入的方式快速解决
2. 对应新的项目,可以使用代理服务的方式规范开发
3. 处理多个项目时,可以通过 nginx 配置多个端口来降低服务重启的成本
另外在方案的细节处可以多一些思考,比如:
1. 依赖平台服务,若服务处于维护状态,接口则不可使用。【可通过平台指导文档在本地搭建服务器,减少对平台的依赖】
2. 框架代理配置接口较多时,可以在请求拦截器中添加请求前缀 /api,在代理配置统一转发/api 的请求
评论