前端 mock 数据
程序员文章站
2022-03-18 17:03:34
...
前端 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/json
app.use(bodyParser.json())
// 解析 application/x-www-form-urlencoded
app.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 mockLastIndex
const 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/json
app.use(bodyParser.json())
// 解析 application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({
extended: true
}))
const mockRoutes = registerRoutes(app)
var mockRoutesLength = mockRoutes.mockRoutesLength
var mockStartIndex = mockRoutes.mockStartIndex
chokidar.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 cache
unregisterRoutes()
const mockRoutes = registerRoutes(app)
mockRoutesLength = mockRoutes.mockRoutesLength
mockStartIndex = mockRoutes.mockStartIndex
console.log('请求更新!')
} catch (error) {
console.log('请求更新出错:', error)
}
}
})
}
用node启动一个本地服务,来实现mock
在项目根目录建一个mockServer.js文件:
let express = require('express') // 引入express
let Mock = require('mockjs') // 引入mock
let app = express() // 实例化express
app.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服务