“This is the 22nd day of my participation in the Gwen Challenge in November. Check out the details: The Last Gwen Challenge in 2021.”

In the last article, we saw how to implement a mock service by emulating XMLHttpRequest by looking at the MockJS source code and the XMLHttpRequest interface description, as described in the following article:

Implement Mock services by emulating XMLHttpRequest

This article looks at how to register a mock service with the power of Webpack.

Understand WebpackDevServer

Webpack provides a simple Web server through webpack-dev-server and can be reloaded in real time. It tells the service started by Webpack-dev-Server which directory file to use as the accessible file by configuring the contentBase parameter, commonly known as the root path of the service. DevServer also exposes a before tick sub-function, which provides the ability to customize middleware within the service before all other middleware, so you can define mock handlers within the before function, match routes, intercept requests, and return mock data.

So what is the devServer that WebPack starts with? We know from looking at the source code that it is an instance of Express.

Express framework

Express is a fast, open and minimalist Web development framework based on node. js platform.

Let’s take a look at the basic usage of Express so we can write a mock service and what it is.

1. Install

Initialize a project with NPM init, then perform naming:

npm install express --save
Copy the code

2. Hello World

var express = require('express') // 1. Var app = express() // 3. Get ('/', function (req, res) {res.send('hello world')}) // 2. App.listen (3000)Copy the code

When you make a get request with path /, it returns Hello World. It’s that simple.

3. Develop log middleware

Middleware functions are functions that can access functions in the request object (REQ), response object (RES), and next application request-response loop. The next function is a function in the Express router that, when called, executes the middleware after the current middleware.

Var myLogger = function (req, res, Use (myLogger) app.get('/', function (req, function (req, function (req, function (req, function (req, function (req, function (req, function (req, function (req, function))) res) { res.send('Hello World! ') }) app.listen(3000)Copy the code

Each time an application receives a request, it prints a message “LOGGED” to the terminal.

4. Express API

Here are just a few of the methods we need to use.

  1. App. get: Get request
  2. App. post: Indicates a POST request
  3. App. delete: Deletes a request
  4. App. put: Put request

Mock service implementation

From the above we know that webpackDevServer is express itself, and it exposes the before hook function and it runs before all middleware, as well as the AppExpress instance in the before function. Therefore, we can register the service through the APP.

1. Basic implementation

devServer: { before: (app)=>{ app.get('/app/test',(req,res)=>{ res.send('Hello World! ')})}}Copy the code

This is where you register a mock service that returns Hello World with a route of /app/test. How do you access it? This is mounted on webpackDevServer, so it can be accessed directly through the IP + port of the devServer that is started. The project can be accessed directly from axios.get(‘/app/test’).

2. Advanced: dynamic registration

In a real project, it is not possible to write before every time and then restart. On the one hand, it will lead to webpackDevServer code bloated, difficult to maintain; On the other hand, changes restart webPack, which is inefficient. Therefore, it is highly recommended to create a folder for mock services, and to listen for changes in the folder within devServer for automatic registration.

The corresponding code is as follows: without too much description, you can try it yourself. Key technical points are:

  1. throughchokidarListen for file changes
  2. Understand the commonJs implementation mechanism.

CommonJs implements portal: Do you really master commonJs? Let’s take a look at the underlying implementation

// mock-server.js const chokidar = require('chokidar') const bodyParser = require('body-parser') const chalk = require('chalk') const path = require('path') const mockDir = path.join(process.cwd(), Function registerRoutes(app) {let mockLastIndex const {default: Mocks} = require('./index.js') for (const mock of mocks) {// Register mock app[mock.type](mock.url, mock.response) mockLastIndex = app._router.stack.length } const mockRoutesLength = Object.keys(mocks).length return { mockRoutesLength: mockRoutesLength, mockStartIndex: MockLastIndex - mockRoutesLength}} function unregisterRoutes() {/* * require. Therefore, a cache is saved at runtime. Removing this cache results in new module executions and new exports. */ Object.keys(require.cache).forEach(i => { if (i.includes(mockDir)) { delete require.cache[require.resolve(i)] } }) } Module. exports = app => {// es6 polyfill require('@ / Babel /register') // https://expressjs.com/en/4x/api.html#req.body app.use(bodyParser.json()) app.use(bodyParser.urlencoded({ extended: true })) const mockRoutes = registerRoutes(app) var mockRoutesLength = mockRoutes.mockRoutesLength var mockStartIndex = MockRoutes mockStartIndex / / monitor file, heat load mock - server chokidar. Watch (mockDir, {ignored: / mock - server/ignoreInitial: true }).on('all', (event, Path) = > {the if (event = = = 'change' | | event = = = 'add') {try {/ / remove routing stack simulation app. _router. Stack. The splice (mockStartIndex, 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

conclusion

Mock service registration is not difficult. It is mock data construction that consumes time. Is there a way to improve this area? Automate the mock service generation. The answer is: yes. Write another article to explain it in detail.