diff --git a/mock/index.js b/mock/index.js index 7d9609ab..08cdc471 100644 --- a/mock/index.js +++ b/mock/index.js @@ -1,11 +1,23 @@ import Mock from 'mockjs' -import mocks from './mocks' import { param2Obj } from '../src/utils' -const MOCK_API_BASE = '/mock' +import user from './user' +import role from './role' +import article from './article' +import search from './remoteSearch' +const mocks = [ + ...user, + ...role, + ...article, + ...search +] + +// for front mock +// please use it cautiously, it will redefine XMLHttpRequest, +// which will cause many of your third-party libraries to be invalidated(like progress event). export function mockXHR() { - // 修复在使用 MockJS 情况下,设置 withCredentials = true,且未被拦截的跨域请求丢失 Cookies 的问题 + // mock patch // https://github.com/nuysoft/Mock/issues/300 Mock.XHR.prototype.proxy_send = Mock.XHR.prototype.send Mock.XHR.prototype.send = function() { @@ -42,9 +54,10 @@ export function mockXHR() { } } +// for mock server const responseFake = (url, type, respond) => { return { - url: new RegExp(`${MOCK_API_BASE}${url}`), + url: new RegExp(`/mock${url}`), type: type || 'get', response(req, res) { res.json(Mock.mock(respond instanceof Function ? respond(req, res) : respond)) diff --git a/mock/mock-server.js b/mock/mock-server.js new file mode 100644 index 00000000..99346afb --- /dev/null +++ b/mock/mock-server.js @@ -0,0 +1,79 @@ +const chokidar = require('chokidar') +const bodyParser = require('body-parser') +const chalk = require('chalk') + +function registerRoutes(app) { + const { default: mocks } = require('./index.js') + for (const mock of mocks) { + app[mock.type](mock.url, mock.response) + } + return { + mockRoutesLength: Object.keys(mocks).length + } +} + +function unregisterRoutes() { + Object.keys(require.cache).forEach(i => { + if (i.includes('/mock')) { + delete require.cache[require.resolve(i)] + } + }) +} + +function getPath(path) { + var match = path.toString() + .replace('\\/?', '') + .replace('(?=\\/|$)', '$') + .match(/^\/\^((?:\\[.*+?^${}()|[\]\\\/]|[^.*+?^${}()|[\]\\\/])*)\$\//) + return match + ? match[1].replace(/\\(.)/g, '$1').split('/') + : path.toString() +} + +function getMockRoutesIndex(app) { + for (let index = 0; index <= app._router.stack.length; index++) { + const r = app._router.stack[index] + if (r.route && r.route.path) { + const path = getPath(r.route.path) + if (path.includes('mock')) { + return index + } + } + } +} + +module.exports = app => { + // es6 polyfill + require('@babel/register') + + // parse app.body + // http://expressjs.com/en/4x/api.html#req.body + app.use(bodyParser.json()) + app.use(bodyParser.urlencoded({ + extended: true + })) + + const { mockRoutesLength } = registerRoutes(app) + + // watch files, hot reload mock server + chokidar.watch(('./mock'), { + ignored: 'mock/mock-server.js', + persistent: true, + ignoreInitial: true + }).on('all', (event, path) => { + if (event === 'change' || event === 'add') { + // find mock routes stack index + const index = getMockRoutesIndex(app) + + // remove mock routes stack + app._router.stack.splice(index, mockRoutesLength) + + // clear routes cache + unregisterRoutes() + + registerRoutes(app) + + console.log(chalk.magentaBright(`\n > Mock Server hot reload success! changed ${path}`)) + } + }) +} diff --git a/mock/mocks.js b/mock/mocks.js deleted file mode 100644 index 84a25ddc..00000000 --- a/mock/mocks.js +++ /dev/null @@ -1,12 +0,0 @@ -import user from './user' -import role from './role' -import article from './article' -import search from './remoteSearch' - -export default [ - ...user, - ...role, - ...article, - ...search -] - diff --git a/package.json b/package.json index 12bf3ffc..f8f98543 100644 --- a/package.json +++ b/package.json @@ -82,6 +82,7 @@ "babel-eslint": "10.0.1", "babel-jest": "23.6.0", "chalk": "2.4.2", + "chokidar": "2.1.5", "connect": "3.6.6", "eslint": "5.15.3", "eslint-plugin-vue": "5.2.2", diff --git a/vue.config.js b/vue.config.js index 7b9d2dbb..d3a08991 100644 --- a/vue.config.js +++ b/vue.config.js @@ -41,22 +41,7 @@ module.exports = { } } }, - after(app) { - require('@babel/register') - const bodyParser = require('body-parser') - - // parse app.body - // http://expressjs.com/en/4x/api.html#req.body - app.use(bodyParser.json()) - app.use(bodyParser.urlencoded({ - extended: true - })) - - const { default: mocks } = require('./mock') - for (const mock of mocks) { - app[mock.type](mock.url, mock.response) - } - } + after: require('./mock/mock-server.js') }, configureWebpack: { // provide the app's title in webpack's name field, so that