在开发基于api交互、前后端分离的网页应用时,经常会遇到几个问题:
- 前端页面已经编排好了,但是后台接口还没准备好,或者是突然出现Bug,这样没办法进行对接测试。
- 我们希望服务器返回特定类型的数据,以测试某页面在特定条件下是否存在问题,但作为前端我们一般不会接触到后端代码和数据库,每次都找后端添加模拟数据又很麻烦。
为解决这两个问题,最简单的解决办法就是搭建一个mock server,专门返回需要的模拟数据。
webpack-dev-server
是我们开发vue、react时必备的工具,通过webpack-dev-server
的before
钩子,可以在webpack-dev-server
上添加我们需要的mock server功能,而不需要另行搭建服务器。
在一通搜索后,我找到了这篇和这个webpack中间件,只需要少许修改就能webpack-dev-server
当做mock server来用,并且对同一URL下的GET
、POST
、PATCH
等不同的HTTP METHOD
做分别处理,支持热切换。
使用方法很简单,在webpack.dev.conf.js
的devServer
中添加新钩子before
,将所有请求交由apiMocker
处理,然后当需要使用模拟数据时,只需要将请求的URL改为webpack服务器上既可。
npm install webpack-api-mocker --save-dev复制代码
const apiMocker = require('webpack-api-mocker')config = { ... devServer: { before(app) { apiMocker(app, path.resolve('mock/api.js')) } } ...}复制代码
api.js
const fs = require('fs');function fromJSONFile(filename) { return (req, res) => { const data = fs.readFileSync(`mock/data/${filename}.json`).toString(); const json = JSON.parse(data); return res.json(json); };}const proxy = { 'GET /app/user/profile': fromJSONFile('profile'),};module.exports = proxy;复制代码
修改URL
axios.get('user/info').then(...)// 修改URL,加上前缀axios.get('http://127.0.0.1:8080/' + 'user/info').then(...)复制代码
更进一步
经过上面的步骤,mock server已经基本能运行了,但还是有一些不友好。每次需要使用模拟数据时,都要修改项目源码,改写请求的URL,在测试完毕后还得再改回来,如果该请求在源码内有多处地方使用,那改动的地方就多了,比较麻烦。我们可以再进行一些改进。
改进的思路就是开启mock server后,将所有对api服务器的请求都发送到webpack server
上,webpack server
拦截并处理所有已定义有模拟数据的接口请求,而未定义的接口请求则转发到api服务器上。
上面说的那个项目作者已经合并了我的PR,下面这段可以不用理了,继续用上面那个
首先,我们要对前面用到的那个中间件进行改进,修改后的代码在我的,插件主要就一个文件
index.js
,复制下来直接使用即可。修改了那些内容可以看
然后添加一个新的npm命令dev-mock
,定义一个环境变量MOCK
来控制是否开启mock server
:
"script": { "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",+ "dev-mock": "MOCK=true webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",}复制代码
webpack config中当MOCK
变量存在时才开启mock server
config = { ... devServer: { if (process.env.MOCK) { before(app) { apiMocker(app, path.resolve('mock/api.js'), { proxy: { '/app//*': 'http://api.leaderlegend.com', } }); } } } ...}复制代码
为了在代码中使用环境变量MOCK
,我们要在webpack config内传递该值。如何传值参考StackOverflow上的这个回答。
config = { ... devServer: ... plugins: [ new webpack.DefinePlugin({ 'process.env': { NODE_ENV: process.env.NODE_ENV, MOCK: process.env.MOCK, } }), ... ] ...}复制代码
通过判断环境变量MOCK
来确定api服务器地址,这里最好保持第一个path相同以更方便转发
const BASE_URL = process.env.MOCK ? 'http://127.0.0.1:8080/app/' : 'http://api.harlanluo.com/app/';复制代码
到此为止已经全部完成,需要使用模拟数据时,使用npm run dev-mock
命令来运行,,不需要时则使用npm run dev
,无需对项目源码对做任何修改。