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:

  • throughbodyParserParse the request
  • throughregisterRoutesregisteredmockRoutes
  • throughchokidarListen 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 themock/index.jsThe introduction of themocks
  • Then traversemocksPass byresponseFakeTo get back
  • Then traversemockForServerThrough 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.