寰宇网

vue-cli webpack模板mock数据的方法

vue-cli是Vue提供的脚手架生成工具,类似于yeoman,它提供的webpack模板非常好用。但在前后端分离的开发模式下,没有提供较好的mock数据的方案。应该是留给用户自己解决,毕竟mock数据的方案比较多。我这里只介绍通过修改改模板的express服务器,添加一些路由的形式来使本地的json文件作为服务器响应返回来提供mock数据。

问题是这样的,之前用的团队高工配置的脚手架,也是Vue框架的,它很多功能不如vue-cli提供的好用,但是mock数据部分让我印象深刻,一个项目如果想让后续的开发者、维护者上手就可以开始工作,提供一份完备的mock数据是最好的方式。

之前的项目就是能轻易跑起来看效果的,除了少部分赶工直接和后端连着做的部分,其它部分都是有相应的mock数据的。效果就是ajax请求发给了本机,获取到了假数据,程序可以继续跑下去。实现方式上是通过webpack-dev-server的proxy功能。

相关文档在这里,http://webpack.github.io/docs/webpack-dev-server.html#proxy

具体代码不写了,因为今天要说的是改造vue-cli提供的webpack模板,使之有类似的mock功能。

首先,要仔细阅读vue-cli的模板说明,查看其是否已经提供了该功能。如链接,其模板提供了开发时API的proxy功能,是基于http-proxy-middleware插件实现的,看上去好像不用额外做什么事了,但按照文档试了一下,它所提供的功能和我想要的似乎有些不一致。

就我目前的理解和尝试,结合相关文档,该proxy功能应该是说,有后端接口在线上运行,但是直接请求有跨域问题,或者是该项目只是MVC中的V层,在开发完成后会被放到后端模板中由后端进行渲染,所以请求往往是“/testapi”,而开发时本机服务器是node-express,并没有相应的API。通过该代理,把“/testapi”代理到真实的API去。

而我的需求是我没有后端,我只有和后端约定好的接口文档和mock数据,我希望访问“http://targethost/apixxx”,能拿到我的mock数据。

再查查是否已经有人做好了且有完善的教程,大部分都是讲理由mock.js或者线上mock服务,或者还是刚刚那个http-proxy-middleware中间件实现的方法。

在尝试了一些奇怪的方法后,突然想起,express是一个相当简单的nodejs的服务器端框架啊,可以直接修改项目的dev-server.js,对express加一些路由来处理相应的mock数据响应就好了。

具体操作方法:在build/dev-server.js中找到staticPath,在app.use(staticPath ……)后,加一个app.use(‘/api1’, express.static(‘../mock/api1.json’)),如果已经在npm run dev状态下要重启服务器(ctrl+c,再重新执行npm run dev)才能生效。

通过这样的方式,我们就实现了对“/api1”的mock,在项目代码中对”localhost:8080/api1”进行请求就能拿到希望拿到的api1.json文件中的内容作为响应了。

唔,可能有人问,这个localhost:8080不是我最终希望请求的url啊,最后上线还要一一修改岂不是很麻烦?把所有的api的url都放在一个js中,export出来即可。在这一个文件中,把url拆成baseUrl + apiPath的形式,最后只需要改baseUrl即可。如果还嫌麻烦,配置一下它和运行环境的变量的关系即可,在dev模式下,请求localhost,在qa模式下请求RD的ip,在product模式下,请求线上地址。

给一个简单的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* @file 请求URL配置文件
*/
// 开发mock地址
let host = 'http://localhost:8080/';
// 联调地址
// let host = 'http://api.test.com/';
// 上线地址
// let host = 'http://api.production.com/';
export default {
login: host + 'Login',
logout: host + 'Login/Logout',
reg: host + 'Register',
// 省略
}

通过该文件聚合所有的api url,比如这个login,我们希望拿到:

1
2
3
4
5
6
{
"status": 0,
"data": {
"name": "test"
}
}

就在项目根目录创建文件夹mock,内放文件login.json,内容如上。

然后在build/dev-server.js中,上文提到的地方,加上app.use(‘/login’, express.static(‘../mock/login.json’))。再在登录按钮上绑事件,向server发起login请求,就能收到希望的返回了。

不过这种方式只能是get请求,如果是post请求,可以这样写:app.post(‘/login’, function(req, res) {res.send(require(‘../mock/login.json’))});

这样下去dev-server.js会越来越多,越来越大。就可以考虑把这个mock路由提到一个单独的文件来做,比如取名叫mock-map.js,export出一个方法,在dev-server.js中执行这个方法,把app作为参数传入,在mock-map.js中把路由和处理一一写好。

1
2
3
4
5
6
7
8
// mock-map.js
var express = require('express')
module.exports = function (app) {
app.use('/api1', express.static('./mock/db.json'))
app.post('/api2', function (req, res) {res.send(require('../mock/db.json'));});
// 省略
}

OVER.