The first response to this problem is to configure devServer in vue.config.js and redirect traffic to mockServer via a proxy proxy.
So I checked vue.config.js for the first time, and the devServer configuration is as follows:
devServer: {
port: port,
open: true.overlay: {
warnings: false.errors: true
},
before: require('./mock/mock-server.js')}Copy the code
Surprisingly, there is no proxy.
The thread stops here, so let’s take a look at how.env is configured:
# .env.stage
VUE_APP_BASE_API = '/stage-api'
# .env.development
VUE_APP_BASE_API = '/dev-api'
# .env.production
VUE_APP_BASE_API = '/prod-api'
Copy the code
How did this project find the server after it was packaged?
With this question in mind, a global search of VUE_APP_BASE_API yielded the next clue:
Mock -server.js is the key to mock-server.js. If you look at vue.
devServer: {
/ *... * /
before: require('./mock/mock-server.js')}Copy the code
Back to mock-server.js, where we focus on the module.exports method:
module.exports = app= > {
app.use(bodyParser.json())
app.use(
bodyParser.urlencoded({
extended: true}))const mockRoutes = registerRoutes(app)
var mockRoutesLength = mockRoutes.mockRoutesLength
var mockStartIndex = mockRoutes.mockStartIndex
chokidar
.watch(mockDir, {
ignored: /mock-server/,
ignoreInitial: true
})
.on('all'.(event, path) = > {
if (event === 'change' || event === 'add') {
try {
app._router.stack.splice(mockStartIndex, mockRoutesLength)
unregisterRoutes()
const mockRoutes = registerRoutes(app)
mockRoutesLength = mockRoutes.mockRoutesLength
mockStartIndex = mockRoutes.mockStartIndex
console.log(
chalk.magentaBright(
`\n > Mock Server hot reload success! changed ${path}`))}catch (error) {
console.log(chalk.redBright(error))
}
}
})
}
Copy the code
After a rough analysis, it is easy to see that it does three things altogether:
- through
bodyParser
Parse the request - through
registerRoutes
registeredmockRoutes
- through
chokidar
Listen to the mock directory to implement hot updates to mock-Server
RegisterRoutes = registerRoutes = registerRoutes = registerRoutes
function registerRoutes(app) {
let mockLastIndex
const { mocks } = require('./index.js')
const mocksForServer = mocks.map(route= > {
return responseFake(route.url, route.type, route.response)
})
for (const mock of mocksForServer) {
app[mock.type](mock.url, mock.response)
mockLastIndex = app._router.stack.length
}
const mockRoutesLength = Object.keys(mocksForServer).length
return {
mockRoutesLength: mockRoutesLength,
mockStartIndex: mockLastIndex - mockRoutesLength
}
}
Copy the code
As you can see, the logic is as follows:
- First of all, from the
mock/index.js
The introduction of themocks
- Then traverse
mocks
Pass byresponseFake
To get back - Then traverse
mockForServer
Through theapp[mock.type](mock.url, mock.response)
To register
Let’s see what Mocks looks like first:
/* index.js */
const user = require('./user')
const role = require('./role')
const article = require('./article')
const search = require('./remote-search')
const mocks = [...user, ...role, ...article, ...search]
Copy the code
/* user.js */
const tokens = {
admin: {
token: 'admin-token'
},
editor: {
token: 'editor-token'}}const users = {
'admin-token': {
roles: ['admin'].introduction: 'I am a super administrator'.avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif'.name: 'Super Admin'
},
'editor-token': {
roles: ['editor'].introduction: 'I am an editor'.avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif'.name: 'Normal Editor'}}module.exports = [
// user login
{
url: '/vue-element-admin/user/login'.type: 'post'.response: config= > {
const { username } = config.body
const token = tokens[username]
// mock error
if(! token) {return {
code: 60204.message: 'Account and password are incorrect.'}}return {
code: 20000.data: token
}
}
},
// get user info
{
url: '/vue-element-admin/user/info\.*'.type: 'get'.response: config= > {
const { token } = config.query
const info = users[token]
// mock error
if(! info) {return {
code: 50008.message: 'Login failed, unable to get user details.'}}return {
code: 20000.data: info
}
}
},
// user logout
{
url: '/vue-element-admin/user/logout'.type: 'post'.response: _= > {
return {
code: 20000.data: 'success'}}}]Copy the code
So we get the rough structure of Mocks:
mocks = [
{
url: string,
type: string,
response: function | object}]Copy the code
Back in mock-server, let’s see what responseFake does:
const responseFake = (url, type, respond) = > {
return {
url: new RegExp(`${process.env.VUE_APP_BASE_API}${url}`),
type: type || 'get'.response(req, res) {
console.log('request invoke:' + req.path)
res.json(
Mock.mock(respond instanceof Function ? respond(req, res) : respond)
)
}
}
}
Copy the code
Obviously, this function is handling the mock interface, and finally we return to registration:
for (const mock of mocksForServer) {
app[mock.type](mock.url, mock.response)
mockLastIndex = app._router.stack.length
}
Copy the code
How do you register?
Take a look at the WebPack documentation:
Finally, the brain map of the whole analysis is added:
conclusion
Now that we’ve seen how vue-element-admin implements mock-Server, there’s just one problem: The.env.prodcution and.env.stage are not configured with the address of the remote server. How does it find the server after packaging?
However, this problem is not discussed in this chapter, the packaging chapter will be analyzed separately.