preface

In order to better improve the efficiency of development, need not frequent refresh the browser to see the effect, webpack provides us with HotModuleReplacementPlugin, hereinafter referred to as HRM. I’m sure you all know what it does. Yes, the most direct effect is that we can go to the browser and see the changes directly after we save the code, without having to refresh the browser every time we change it. This is definitely a powerful tool. So why does it do this, or what magic does it use? Let’s find out.

Directions for use

Any project that uses Webpack requires a webpack.config.js configuration file. That can be configured directly:

module.exports = {
 ...
  devServer: {
    hot: true,
  },
  plugins: [
    new HtmlWebpackPlugin(),
    new webpack.HotModuleReplacementPlugin()
  ]
 ...
}

Copy the code

The followingnew webpack.HotModuleReplacementPlugin()The instantiation step can be omitted. If we start webpack or webpack-dev-server with the –hot option in the project, the plugin will be added automatically. Of course, there are no adverse reactions on the configuration.

This way you can make changes that are saved in the browser to automatically refresh and modify the view.

Then this function is more op, please do not blink temporarily. Without further ado, let’s look at the code.

let div = document.createElement('div')
document.body.appendChild(div)

let render = function () {
  let text = require('./text.js')
  div.innerHTML = text
}

render()

if (module.hot) {
  module.hot.accept(['./text.js'], render)
}

Copy the code

Very simple little function, import a JS script, and assign its contents to div. The key is the following module.hot.accept(), what is it?

module.hot.accept()

This thing is like this, if the project by HotModuleReplacementPlugin this plug-in is enabled in the Hot Module Replacement, so will be in the Module. Under the Hot exposed its interface, the accept () is the Module API.

If we modify the module configured in Accept (), the module will be updated, which is a partial update to the page, and the page will not be refreshed. This is where WebPack optimizes the project.

If there are so many modules in our project, do they have to be added to this API? For the VUE project, vue-Loader will do it for us. You can take a look at the vue-loader source code to know.

Module.hot. accept(dependencies, // can be a string or an array of strings callback // function triggered after module update)Copy the code

If the specified module is updated, you should specify that the module is not updated. Decline () is used to do this.

Actual operation in the project

We can see what this actually looks like: after modifying the module content and saving it, two files are generated in the browser’s Network:

Json ‘file and main+hash +’.hot-update.js’ file. The former returns the modified module with a new hash value that will appear as the filename for the next modification. The latter returns the webpackHotUpdate() method, which includes the module name and the modified contents of the module.

In fact, the update of Webpack is afterwebpackHotUpdateHandle modified modules with content, again through customhotCreateRequire()Method to insert a module into a page.

Server-side process

Webpack listens for files

First, Webpack builds with the Compiler, and then calls Watch to listen to the file.

const compiler = webpack(config) ... Compiler. Watch ({}, () = > {the console. The log (' listening to compile successfully ')})Copy the code

The web server

Create an HTTP service with a Websoket link.

const compiler = webpack(config)
const server = new Server(compiler)
Copy the code

Establish a connection between webpack and web server

SetupDevMiddleware () {this. Middleware = this. WebpackDevMiddleware () / / return a express middleware} webpackDevMiddleware () {/ /... / / after the packaging file write/read memory let fs = new MemoryFS () enclosing the fs = compiler. OutputFileSystem = fs / / generates a middleware in response to the client request file}Copy the code

The reason why memory is used here is that if Webpack's Watch mode is used, it will be stored to the local hard disk every time after packaging. IO operation takes a lot of time. What we need is the real-time performance of local development, and efficiency is the standard.

The browser connects to the WebPack server

The Webpack-hot-Middleware plugin provides communication between the browser and the Webpack server, and receives updates from the Webpack server on the browser side.

io.on('connection', (socket) => { ... Socket. emit('hash', this.currenthash) // Returns a new hash value socket.emit(' OK ')... })Copy the code

The two hash.xx files mentioned above are returned here. So at this point after we change the page code, webPack recompiles, and then notifies the browser that we’re done. These are the things that the server side does.

Client flow

Connect to the WebSocket server

The Websocket client mainly listens for hash and OK, saves the hash value as the file name of the module update, and listens for OK mainly performs the reloadApp method to update.

Do support hot update reloadApp judgment (whether or not to use HotModuleReplacementPlugin)

// reloadApp if (hot) {emit = new EventEmitter(); hotEmitter.emit('webpackHotUpdate', currentHash); } else if (liveReload) { ... window.location.reload(); }Copy the code

hotCheck

Send a request to the server to get the compiled hash value and the updated module name

The ajax request is sent to the server, which returns a hash.hot-update.json file containing the hash value and module name

Update the packaged JS content

The hotCreateRequire method calls hotDownloadUpdateChunk and gets the latest module code via a JSONP request, namely main.hash.hot-update.js

Update module code

Hot updates are made by calling the hotApply method. There is more logic in this method. Call hotUpdate to find the old module and add the new module to modules. The new code is then executed through require. The old module is finally removed from the cache. This is just the general process.

conclusion

Records from the initial curiosity about Webpack-dev-server, to search for documentation, and then to a period of learning. Slowly understand the hot update thing. These frameworks are fascinating, and you don’t want to stop when you start. It’s not as good as writing, but it’s nice to be able to go through the process. These things are not used in the daily business development, but also virtually serve the business.

Come on.