With Webpack packaging, it is unavoidable to use the Hot module replacement feature, which enables you to modify, add, or delete the module code in the front-end page without refreshing the page. How exactly does it work? This article mainly from debugging tools, configuration files, official documents three aspects of the analysis.
Debugging Tools
Let's start with the Chrome Debug tool network and see what happens between the page and the backend when the code changes.
Page Initial load
We see that in addition to loading the page depends on the file, there is a connection, this is a server-sent Events, the relevant introduction can refer to this article, and every time will be sent to the data. Data content is mainly
Action:sync operation;
HASH:F397E485C539FD7A10FB, is the bundle of hash, because and output file Collections.f397e485c539fd7a10fbjs content hash value is the same;
Modules: The module ID in the output bundle and the corresponding file address.
Modify Code
Then modify a code, Webpack automatically compiled, found that there are several changes in the network, the first is the client received the back-end event
Action:built operation, notify browser Webpack re-initiated the compilation;
Hash: The contents of the latest output bundle hash value is debc36315df6764f157c;
The module ID in the Modules:bundle and the file address of the corresponding module.
In addition, the front-end initiated two requests to the backend, requesting F397e485c539fd7a10fb.hot-update.json and 0.f397e485c539fd7a10fb.hot-update.js two files, The hash value of the file is exactly the bundle hash value of the backend sending front end before the modification.
Let's take a look at the contents of the two files.
Contents of the JSON file:
H:debc36315df6764f157c,bundle the latest hash value of the content;
C: "0": true, indicating that the bundle ID 0 file has been modified;
JS file contents:
The content is a function, similar to the return form of JSONP, that is, the page received the request after the execution of the Webpackhotupdate function, the bundle ID 0 in the file of the Moudle ID 50 module to modify.
Follow up here, and we can speculate on this interactive process:
(0) Webpack The code of how to update the update module (UPDATE-METHOD) and receive back-end push events (Event-source) to the bundle at first compile time;
(1) Webpack enter watch mode and recompile when the project code changes;
(2) The compiled output is stored in Dev-server, where the compilation is only for the changing module, and the output should contain the Oldbundlehash.hot-update.json and oldbundlehash.hot-update.js files mentioned above;
(3) Sending built events to the front end using Hot-middleware middleware in dev-server;
(4) After the front-end notification, the back end of the request for the latest changes in the file, the request to the JS file through the script tag to execute after loading, in fact, the implementation has been embedded into the bundle function (Update-method), thereby modifying the bundle file.
Configuration file
Next we verify from the project configuration file that the configuration file primarily refers to the WEBAPCK project in VUE-CLI.
Webpack.dev.conf.js
There are two main places involved in hot Module replacement:
Entry Configuration: The introduction of Event-source at the beginning of each portal bundle, that is, receiving events sent from the backend on the page
/*********./build/webpack.dev.conf.js********/
Add Event-source related code to each portal chunk as part of the HRM runtime. The corresponding configuration of the backend is shown in the Hotmiddleware section of Dev-server Object.keys (basewebpackconfig.entry). ForEach (function (name) { Basewebpackconfig.entry[name] = ['./build/dev-client '].concat (Basewebpackconfig.entry[name])})
/*********./build/dev-client.js********///Event-source object for receiving server-side push events// Eventsource-polyfill is used to extend the compatibility of Event-source objects under Internet Explorer require (' Eventsource-polyfill ') var hotclient = require (' Webpack-hot-middleware/client?noinfo=true&reload=true ')//is primarily used to accept notification of back-end Hotmiddleware, Perform reload operation Hotclient.subscribe (function (event) { if (event.action = = = ' Reload ') { window.location.reload () }})
plug-in configuration: introduce the Hotmodulereplacementplugin plug-in, Update-method code into the bundle
Plugins: [... The HMR plugin embeds the HMR runtime code into the bundle and is able to manipulate the app code and complete the code to replace the new Webpack. Hotmodulereplacementplugin (), //Error prompt Plug-in: Error does not block, but after compiling a hint to the new Webpack. Noemitonerrorsplugin (), new Friendlyerrorsplugin () ]
Dev-server.js
There are two main places involved in hot Module replacement:
Mount compiler on Devmiddleware: provides static file service for compiled output
Mount the compiler on the Dev-server, listen for local code changes, change to start compiling and staging the compiled file into memory var devmiddleware = require (' Webpack-dev-middleware ') ( Compiler, { PublicPath:config.dev.assetsPublicPath = = = './'? ": Config.dev.assetsPublicPath, quiet:true})
mount the compiler on Hotmiddleware: notifies the front-end event-source that an object has occurred rebuilt
After compiling the notification to the HRM RUNTIME,HRM runtime after receiving the update notification, download the updated module, notify the app update, the app receives the notification, and then request the HRM Runtime execution module to replace var hotmiddleware = Require (' Webpack-hot-middleware ') (compiler, { log: () + = {}})
The inference that is obtained by the network debug before the configuration file can be basically verified, then take a look at the official document verification.
Official documents
The Official document first introduces the basic principles of hot Module replacement, then introduces several knowledge points in the principle.
Basic principle
WEBAPCK in the process of compiling, the HMR runtime is embedded into the bundle; After the compilation, webpack the project code file to monitor, found the file changes recompile the change module, and notify HMR Runtime, and then HMR Runtime loads the changed module file and attempts to perform a hot update operation. The logic of the update is: first check whether the module can support the Accept method, if not supported, then bubble find the parent node of the module tree, until the Ingress module, the Accept method is the module Hot-replace handler.
Knowledge points
(1) compiler
Here compiler refers to the WEBAPCK, mainly provide update information, that is, update menifest (JSON file format) and update chunks (JS file format);
(2) App
The app refers to the front page, the code in the app calls the HMR runtime to download the latest module code, and then calls the HMR runtime to perform the update operation;
(3) HMR Runtime
HMR Runtime is the code embedded into the front page of the WEBAPCK, mainly provided to provide a functional check and apply. Check is used to download the latest module code, the runtime can receive the back-end send the event and send the request, apply to update the module, the module will be updated mainly to tag, and then call the module (and possibly the parent module) update handler to perform the update.
(4) Module
HRM is a pluggable tool that only affects modules that contain HMR code. In general, it is not necessary to write HMR code for each module, and the update will be bubbling to check if HMR code is present.
According to the official documentation, the Basic agreement with our inference is that the official document introduces the concept of the HMR runtime, which can be seen as a combination of event-source and update-method in inference.
Now you should be clear about the fundamentals of Webpack's Hot module replacement, the official documentation mentions how to replace the old module with the latest module, which is presented in the next article.
Hot Module replacement operating mechanism of Webpack