前端 mock 数据
Easy Mock
由于easy mock线上服务基本打不开的情况,所以有能力的还是做一下本地部署(参考)
在easymock创建一个项目,并将项目的 Base URL 配置到axios的 baseURL,easymock不需要解决跨域的问题。
Yapi
公司内部的话也可以做一下内网部署
用法和easymock差不多,将yapi内项目的mock地址配置到axios的baseURL,也不需要解决跨域的问题
vue cli3 配置本地 mock 数据
通过webpack的 devServer.before 来实现
module.exports = {
//...devServer: {
before: function(app, server) {
app.get('/some/path', function(req, res) {
res.json({
custom: 'response' });});}}
};
如果mock数据过多,我们可以单独建一个文件夹用来存放:
mock/login.js:
const loginMock = [{
type: 'post',url: '/api/loginPost',res: function (req, res, next) {
console.log(req.body)res.json({
"data": "post" })}},{
type: 'get',url: '/api/loginGet',res: function (req, res, next) {
console.log(req.query)res.json({
"data": "get" })}}
]module.exports = loginMock
mock/index.js:
module.exports = app => {
// 使用Express中间件body-parser来解析请求体const bodyParser = require('body-parser')// 解析 application/jsonapp.use(bodyParser.json())// 解析 application/x-www-form-urlencodedapp.use(bodyParser.urlencoded({
extended: true}))// 引入mock数据const loginMock = require('./login.js')const mocks = [...loginMock,...chartMock]for (const mock of mocks) {
app[mock.type](mock.url, mock.res)}
}
vue.config.js:
module.exports = {
...devServer: {
...// 在服务器内部的所有其他中间件之前执行定制中间件before: require('./mock/index.js'),}
}
按这样配置完后,基本就完成了本地的数据mock。但有一点不足的就是不能够热更新。每当我们重新修改mock数据,需要重新启动服务才能看到最新的mock数据。
解决这个问题我们可以通过chokidar插件来监控mock文件夹的变化,在发生变化时会清除之前注册的mock-api接口,重新动态挂载新的接口,从而支持热更新。
修改mock/index.js:
const bodyParser = require('body-parser') // 使用Express中间件body-parser来解析请求体
const chokidar = require('chokidar') // 文件夹监控
const path = require('path')const mockDir = path.join(process.cwd(), 'mock') // 获取文件夹路径function registerRoutes(app) {
let mockLastIndexconst baseMock = require('./base.js')const chartMock = require('./chart.js')const mocks = [...baseMock,...chartMock]for (const mock of mocks) {
app[mock.type](mock.url, mock.res) // 在express中注册路由mockLastIndex = app._router.stack.length // 获取所有已注册路由的长度}const mockRoutesLength = Object.keys(mocks).length // 获取所有mock数据的长度return {
mockRoutesLength: mockRoutesLength,mockStartIndex: mockLastIndex - mockRoutesLength}
}
// nodejs清除require缓存 参考:https://blog.hellozwh.com/?post=433
function unregisterRoutes() {
Object.keys(require.cache).forEach(i => {
if (i.includes(mockDir)) {
delete require.cache[require.resolve(i)] // require.resolve 相当于把相对路径转化成绝对路径,避免了自己手写的绝对路径跟cache里的key不一致的问题}})
}module.exports = app => {
// 解析 application/jsonapp.use(bodyParser.json())// 解析 application/x-www-form-urlencodedapp.use(bodyParser.urlencoded({
extended: true}))const mockRoutes = registerRoutes(app)var mockRoutesLength = mockRoutes.mockRoutesLengthvar mockStartIndex = mockRoutes.mockStartIndexchokidar.watch(mockDir, {
// 监控当前目录ignored: /index/, // 忽略index.js文件的变更ignoreInitial: true // 忽略对增加文件或者增加文件夹而触发事件}).on('all', (event, path) => {
// 监听除了ready, raw, and error之外所有的事件类型if (event === 'change' || event === 'add') {
// 文件内容改变或新增文件时触发try {
// 删除已经挂载到express的路由app._router.stack.splice(mockStartIndex, mockRoutesLength)// clear routes cacheunregisterRoutes()const mockRoutes = registerRoutes(app)mockRoutesLength = mockRoutes.mockRoutesLengthmockStartIndex = mockRoutes.mockStartIndexconsole.log('请求更新!')} catch (error) {
console.log('请求更新出错:', error)}}})
}
用node启动一个本地服务,来实现mock
在项目根目录建一个mockServer.js文件:
let express = require('express') // 引入express
let Mock = require('mockjs') // 引入mocklet app = express() // 实例化expressapp.use(function (req, res, next) {
res.header('Access-Control-Allow-Origin', '*')res.header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS')res.header('Access-Control-Allow-Headers', 'X-Requested-With')res.header('Access-Control-Allow-Headers', 'Content-Type')next()
})
// mock接口示例
app.post('/api/loginPost', function (req, res) {
res.json(Mock.mock({
'status': 200,'data|1-9': [{
'key|+1': 1,'mockTitle|1': ['肆无忌惮'],'mockContent|1': ['角色精湛主题略荒诞', '理由太短 是让人不安', '疑信参半 却无比期盼', '你的惯犯 圆满', '别让纠缠 显得 孤单'],'mockAction|1': ['下载', '试听', '喜欢']}]}))
})// 实际项目中肯定有很多mock接口,可以分类目建立,然后引入
const loginMock = require('./mock/login.js')
const chartMock = require('./mock/chart.js')
const mocks = [...loginMock,...chartMock
]
// 挂载这些接口
for (const mock of mocks) {
app[mock.type](mock.url, mock.res)
}
// 启用一个端口并监听。注意不能和项目一个端口,会把项目停掉
app.listen('3001', () => {
console.log('监听端口 3001')
})
在vue.config.js里配置跨域代理:
module.exports = {
...devServer: {
...// 跨域代理proxy: {
'/web': {
target: 'http://localhost:3001', // mockServer监听的端口号ws: false,changeOrigin: true}}}
}
在package.json里配置启动命令:
"scripts": {
"mock": "node ./mockServer"
},
yarn mock启动mock服务