原因
起初使用mockjs2进行本地的mock开发,过程中发现控制台中network看不到请求,这再开发中相当不舒服,根本看不到请求接口的参数,对于查询等操作非常不方便,于是开始对项目的mock方式进行了修改,通过vue-cli3的express服务创建。
目录结构
testdata文件夹中,目录对应接口目录进行创建
├── mock
│ ├── testdata
│ │ mock-server.js
│ │ utils.js
├── config
├── public
├── src
...
├── static
.env.mock
package.json
...
启动
我是通过环境变量和模式的方式启动本地mock环境 .env.mock 和 .env.development 进行区分环境,package.json中添加启动mock的命令:
"scripts": {
"local": "vue-cli-service serve --mode mock",
"serve": "vue-cli-service serve",
...
},
.env.mock
NODE_ENV=mock
改造vue.config.js
首先做的就是先通过devServer的功能进行修改
devServer: {
before: require('./mock/mock-server.js'),
port: 8080
},
在before的时候加载mock-server.js 文件
const fs = require('fs-extra')
const path = require('path')
const JSON5 = require('json5')
const Mock = require('mockjs2')
const { delay } = require('./utils.js')
// 接口前缀
const devServerMockUrlMatch = /^\/api\//
async function getMockData(dataFilePath, method) {
const fileJsonPath = `${dataFilePath}.json`
const fileMockjsPath = `${dataFilePath}.mockjs.json`
const fileRestFulPath = `${dataFilePath}$${method.toLowerCase()}.json`
const fileRestFulMockjsPath = `${dataFilePath}$${method.toLowerCase()}.mockjs.json`
const fileExist = await fs.pathExists(dataFilePath)
const fileJsonExist = await fs.pathExists(fileJsonPath)
const fileMockjsExist = await fs.pathExists(fileMockjsPath)
const fileRestFulExist = await fs.pathExists(fileRestFulPath)
const fileRestFulMockjsExist = await fs.pathExists(fileRestFulMockjsPath)
// 先寻找 RESTFul .mockjs.json 文件
if (fileRestFulMockjsExist) {
return fs.readFile(fileRestFulMockjsPath, 'utf8').then(json => JSON.stringify(Mock.mock(JSON5.parse(json))))
}
// 再寻找 RESTFul .json 数据文件
if (fileRestFulExist) {
return fs.readFile(fileRestFulPath, 'utf8')
}
// 再寻找 .mockjs.json 后缀 mock 数据文件
if (fileMockjsExist) {
return fs.readFile(fileMockjsPath, 'utf8').then(json => JSON.stringify(Mock.mock(JSON5.parse(json))))
}
// 再寻找 .json 后缀 mock 数据文件
if (fileJsonExist) {
return fs.readFile(fileJsonPath, 'utf8')
}
// 再寻找无后缀 mock 数据文件
if (fileExist) {
return fs.readFile(dataFilePath, 'utf8')
}
console.error('------- ERROR ------')
console.error('尝试了以下可能的 mock 数据文件,仍没有找到对应的数据')
console.error(`1. ${fileRestFulPath}`)
console.error(`2. ${fileRestFulMockjsPath}`)
console.error(`3. ${fileJsonPath}`)
console.error(`4. ${fileMockjsExist}`)
console.error(`5. ${dataFilePath}`)
return Promise.reject(new Error('没有找到对应mock数据文件'))
}
module.exports = app => {
// 只有环境变量是mock的情况才会进入
if (process.env.NODE_ENV === 'mock') {
console.info('开启本地mock数据调试模式...')
app.all(devServerMockUrlMatch, async (req, res) => {
const { method, originalUrl } = req
console.info(`本地数据请求:[${method}] ${originalUrl}`)
try {
// 响应延迟500ms,模拟请求
await delay(500)
const dataFilePath = originalUrl
.replace(devServerMockUrlMatch, `${path.join(process.cwd(), 'mock/testdata')}$&`)
.replace(/\?.*$/, '')
let data = await getMockData(dataFilePath, method)
res.append('Access-Control-Allow-Origin', true)
try {
data = JSON5.parse(data)
} catch (e) {
const errMsg = `local mock json data parse error (本地测试数据JSON解析错误): ${dataFilePath}`
throw new Error(`${errMsg}\n${e}`)
}
res.json(data)
} catch (err) {
console.error(err)
res.status(500).send(err.stack)
}
})
}
}
utils.js
const chalk = require('chalk')
const delay = function(time) {
return new Promise(resolve => {
setTimeout(() => {
resolve()
}, time)
})
}
const utils = {
delay
}
module.exports = utils
process.on('unhandledRejection', reason => {
console.log(chalk.red(reason))
console.error(reason.stack)
process.exit(1)
})
结束
启动mock环境之后终于可以开心的进行mock开发啦。我现在是直接获取请求中的地址,然后从本地文件中进行查找,所以testdata中的目录可能会因为请求地址比较深而创建多层文件夹,但是有利有弊吧,对于我自己而言,如果通过接口看mock数据只需要按照文件夹进行查找就好,感觉理解起来更方便。如果还有其他更好的方式请多多指教~~
文笔有限,多多指教。