background

Since The devops project structure does not start with the front and back end separation, it is necessary to implement the front and back end separation configuration in local-dev-server, which is also successfully implemented according to the previous clear tutorial, but in the process starts the local service process for the entire Webpack. And the principle of Webpack-dev-server is also a little understanding, simply to understand the knowledge of this aspect, and make a summary

preface

Dev-server. js and dev-client.js are missing from the build folder when using the latest vue-CLI to generate the vue project.

  • Dev-server.js: In previous versions, we built local servers,
  • Ev-client.js: Mainly related to hot overloading

Vue – CLI upgrade to V3.6.0 after 2.9.1, the two files dev-server and dev-client are removed. Dev-serve.js is merged into webpack.dev.conf.js, so now you can’t use dev-server to set the connection excuse. Instead, you can configure it in the devServer object of webpack.dev.conf.js.

// these devServer options should be customized in /config/index.js
  devServer: {
    clientLogLevel: 'warning'.historyApiFallback: {
      rewrites: [
        {
          from: /.*/,
          to: path.posix.join(config.dev.assetsPublicPath, 'index.html'),
        },
      ],
    },
    hot: true// Enable hot overloading, i.e. hot module replacement contentBase:false, // since we use CopyWebpackPlugin.
    compress: true,
    host: HOST || config.dev.host,
    port: PORT || config.dev.port,
    open: config.dev.autoOpenBrowser,
    overlay: config.dev.errorOverlay
      ? {
          warnings: false,
          errors: true,} :false, publicPath: config. Dev. AssetsPublicPath, proxy: config. Dev. ProxyTable, / / set agent, achieve cross-domain quiet, such as:true, // necessary for FriendlyErrorsPlugin
    watchOptions: {
      poll: config.dev.poll,
    },
  },
  
Copy the code

Hot Module Replacement

doubt

  • Webpack can pack different modules into bundles or chunks, but when I was developing webPack HMR, I didn’t find webPack-packed files in my Dist directory. Where did they go?

It turns out that Webpack packs bundle.js files into memory. The reason it doesn’t generate files is that accessing code in memory is faster than accessing files in the file system, and it also reduces the overhead of writing code to files, all thanks to memory-FS. Memory-fs is a dependent library for Webpack-dev-middleware, which replaces webpack’s outputFileSystem with a MemoryFileSystem instance. The code will then be printed out to memory.

The bundle.js file code is stored in memory as a simple javascript object. When the browser requests the bundle.js file, devServer directly finds the stored javascript object in memory and returns it to the browser.

  • The package.json file for Webpack-dev-server depends on the Webpack-dev-middleware library. What role does Webpack-dev-middleware play in HMR?
  • While using HMR, I learned from Chrome Developer tools that the browser communicates with webSocket and webpack-dev-server, but I didn’t find any new module code in the WebSocket message. How does the packaged new module get sent to the browser? Why isn’t the new module sent to the browser with the message via Websocket?

Webpack-dev-server modifiesthe entry property in the WebPack configuration to add webpack-dev-client code so that the final bundle.js file has code to receive WebSocket messages.

Webpack-dev-server calls the Webpack API to listen for the done event of compile. When compile is complete, Webpack-dev-server sends the hash value of the compiled and packaged new module to the browser using the _sendStatus method.

  • When the browser gets the latest module code, how does HMR replace the old module with the new one, and how does the dependency between modules be handled during the replacement process?
  • Is there a fallback mechanism if the module fails to be replaced during hot replacement?

With these questions in mind, I decided to dig deep into the Webpack source code to find the secrets behind HMR.

HMR workflow

  1. First, in Webpack’s Watch mode, a file in the file system changes, WebPack listens to the file changes, recompiles and packages the module according to the configuration file, and saves the packaged code in memory through a simple JavaScript object.
  2. The second step is the interface interaction between Webpack-dev-server and Webpack. In this step, it’s mainly the interaction between Webpack-Dev-middleware of Dev-server and Webpack. Webpack-dev-middleware calls the API exposed by Webpack to monitor code changes and tells Webpack to pack the code into memory.
  3. The third step is a monitoring of file changes by Webpack-dev-server, which is different from the first step in that it does not monitor code changes for repackaging. . When we are in the configuration file is configured with devServer watchContentBase to true, the Server will listen to these configuration static files in the folder change, change will notify the browser after the live for the application to reload. Notice that this is browser refresh, and HMR are two different things.
  4. The fourth step is also the work of the webpack-dev-server code. This step mainly uses sockJS (webpack-dev-server dependency) to establish a websocket long connection between the browser and the server. This tells the browser about the status of the various stages of the Webpack compilation and packaging, as well as the information that the Server listens for static file changes in step 3. The browser performs different operations based on these socket messages. Of course, the most important information passed by the server is the hash value of the new module, and the subsequent steps use this hash value to perform module hot replacement.
  5. The webpack-dev-server/client cannot request updated code and does not perform hot module operations, handing the work back to Webpack. The job of webpack/hot/dev-server is to decide whether to refresh the browser or hot update the module based on the information passed to it by webpack-dev-server/client and the configuration of dev-server. Of course, if you just refresh the browser, there are no further steps.
  6. HotModuleReplacement runtime is the centre of the client HMR, step on it receives hash value passed to his new module, it through JsonpMainTemplate. Runtime sends an Ajax request to the server end, The server returns a JSON that contains the hash values of all the modules to be updated. Once the updated list is retrieved, the module requests the latest module code again via JSONP. These are steps 7, 8 and 9 in the figure above.
  7. In step 10, the HotModulePlugin will compare the old and new modules and decide whether to update the module. After the decision is made, the dependency relationship between the modules will be checked and the dependency references between the modules will be updated.
  8. As a final step, when HMR fails, we fall back to live Reload, which is a browser refresh to get the latest packaging code. Webpack-dev-server uses one of these dependency librarieswebpack-dev-middlewareThe webpack-dev-server that implements HMR starts an Http server that uses Express. This server communicates with the client using the Websocket protocol. When the original file is changed, Webpack-dev-server compilers in real time

The proxy agent

Webpack-dev-server uses a very powerful HTTP request middleware, HTTP-proxy-Middleware, which is one of its dependencies. This middleware can do intermediate forwarding processing to HTTP request, and can well solve the cross-domain problems in development

Refer to the article

  • Webpack HMR Principle Analysis
  • Webpack-dev-Middleware