Skip to content

Commit 90b7c2f

Browse files
authored
feature[Mock]: mock-server support hot reload (PanJiaChen#1850)
PanJiaChen#1849
1 parent f11839c commit 90b7c2f

File tree

5 files changed

+98
-32
lines changed

5 files changed

+98
-32
lines changed

mock/index.js

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,23 @@
11
import Mock from 'mockjs'
2-
import mocks from './mocks'
32
import { param2Obj } from '../src/utils'
43

5-
const MOCK_API_BASE = '/mock'
4+
import user from './user'
5+
import role from './role'
6+
import article from './article'
7+
import search from './remoteSearch'
68

9+
const mocks = [
10+
...user,
11+
...role,
12+
...article,
13+
...search
14+
]
15+
16+
// for front mock
17+
// please use it cautiously, it will redefine XMLHttpRequest,
18+
// which will cause many of your third-party libraries to be invalidated(like progress event).
719
export function mockXHR() {
8-
// 修复在使用 MockJS 情况下,设置 withCredentials = true,且未被拦截的跨域请求丢失 Cookies 的问题
20+
// mock patch
921
// https://github.com/nuysoft/Mock/issues/300
1022
Mock.XHR.prototype.proxy_send = Mock.XHR.prototype.send
1123
Mock.XHR.prototype.send = function() {
@@ -42,9 +54,10 @@ export function mockXHR() {
4254
}
4355
}
4456

57+
// for mock server
4558
const responseFake = (url, type, respond) => {
4659
return {
47-
url: new RegExp(`${MOCK_API_BASE}${url}`),
60+
url: new RegExp(`/mock${url}`),
4861
type: type || 'get',
4962
response(req, res) {
5063
res.json(Mock.mock(respond instanceof Function ? respond(req, res) : respond))

mock/mock-server.js

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
const chokidar = require('chokidar')
2+
const bodyParser = require('body-parser')
3+
const chalk = require('chalk')
4+
5+
function registerRoutes(app) {
6+
const { default: mocks } = require('./index.js')
7+
for (const mock of mocks) {
8+
app[mock.type](mock.url, mock.response)
9+
}
10+
return {
11+
mockRoutesLength: Object.keys(mocks).length
12+
}
13+
}
14+
15+
function unregisterRoutes() {
16+
Object.keys(require.cache).forEach(i => {
17+
if (i.includes('/mock')) {
18+
delete require.cache[require.resolve(i)]
19+
}
20+
})
21+
}
22+
23+
function getPath(path) {
24+
var match = path.toString()
25+
.replace('\\/?', '')
26+
.replace('(?=\\/|$)', '$')
27+
.match(/^\/\^((?:\\[.*+?^${}()|[\]\\\/]|[^.*+?^${}()|[\]\\\/])*)\$\//)
28+
return match
29+
? match[1].replace(/\\(.)/g, '$1').split('/')
30+
: path.toString()
31+
}
32+
33+
function getMockRoutesIndex(app) {
34+
for (let index = 0; index <= app._router.stack.length; index++) {
35+
const r = app._router.stack[index]
36+
if (r.route && r.route.path) {
37+
const path = getPath(r.route.path)
38+
if (path.includes('mock')) {
39+
return index
40+
}
41+
}
42+
}
43+
}
44+
45+
module.exports = app => {
46+
// es6 polyfill
47+
require('@babel/register')
48+
49+
// parse app.body
50+
// http://expressjs.com/en/4x/api.html#req.body
51+
app.use(bodyParser.json())
52+
app.use(bodyParser.urlencoded({
53+
extended: true
54+
}))
55+
56+
const { mockRoutesLength } = registerRoutes(app)
57+
58+
// watch files, hot reload mock server
59+
chokidar.watch(('./mock'), {
60+
ignored: 'mock/mock-server.js',
61+
persistent: true,
62+
ignoreInitial: true
63+
}).on('all', (event, path) => {
64+
if (event === 'change' || event === 'add') {
65+
// find mock routes stack index
66+
const index = getMockRoutesIndex(app)
67+
68+
// remove mock routes stack
69+
app._router.stack.splice(index, mockRoutesLength)
70+
71+
// clear routes cache
72+
unregisterRoutes()
73+
74+
registerRoutes(app)
75+
76+
console.log(chalk.magentaBright(`\n > Mock Server hot reload success! changed ${path}`))
77+
}
78+
})
79+
}

mock/mocks.js

Lines changed: 0 additions & 12 deletions
This file was deleted.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@
8282
"babel-eslint": "10.0.1",
8383
"babel-jest": "23.6.0",
8484
"chalk": "2.4.2",
85+
"chokidar": "2.1.5",
8586
"connect": "3.6.6",
8687
"eslint": "5.15.3",
8788
"eslint-plugin-vue": "5.2.2",

vue.config.js

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -41,22 +41,7 @@ module.exports = {
4141
}
4242
}
4343
},
44-
after(app) {
45-
require('@babel/register')
46-
const bodyParser = require('body-parser')
47-
48-
// parse app.body
49-
// http://expressjs.com/en/4x/api.html#req.body
50-
app.use(bodyParser.json())
51-
app.use(bodyParser.urlencoded({
52-
extended: true
53-
}))
54-
55-
const { default: mocks } = require('./mock')
56-
for (const mock of mocks) {
57-
app[mock.type](mock.url, mock.response)
58-
}
59-
}
44+
after: require('./mock/mock-server.js')
6045
},
6146
configureWebpack: {
6247
// provide the app's title in webpack's name field, so that

0 commit comments

Comments
 (0)