5
votes

All the webpack examples I have looked at so far deal with client side hot module replacement, for example: this and this.

According to the webpack document, one can use EITHER webpack-dev-server OR middlewares (webpack-dev-webpack-dev-middleware and webpack-hot-middleware, along with webpack-hot-middleware/client in a config entry, and integrated into e.g. express js) to enable hot module replacement for client side codes

Is it possible to enable hot module replacement for server side codes? The document does shows an example

var requestHandler = require("./handler.js");
var server = require("http").createServer();
server.on("request", requestHandler);
server.listen(8080);

// check if HMR is enabled
if(module.hot) {
    // accept update of dependency
    module.hot.accept("./handler.js", function() {
        // replace request handler of server
        server.removeListener("request", requestHandler);
        requestHandler = require("./handler.js");
        server.on("request", requestHandler);
    });
}

The document is quite spare in explanation.

So the question is, how would hot module replacement be implemented in server side code without restarting the server? (At the moment, I have nodemon watching server side code to restart the server on file changes)

2
Did you ever find an answer to this? I am struggling with exactly the same thing and I would die for a simple running example with some explanation. Webpack remains pure magic to me... - Stijn de Witt
I finally created my own example at github.com/aunz/mwb/tree/master/examples/basicApp. Have a look. - Green
This is looking good, thanks! - Stijn de Witt
@Green, can you share any links or articles where you got inspired to build this? Looking over the tool I can understand partially what is going on. Would really appreaciate it. - Vlad Nicula
@VladNicula, 1) server codes are watched in this line and run as a forked child in this line. 2) On code changes, a signal 'hmr' is sent to the server in this line. The 'hrm' signal is handled through the "inspired" original signal.js which either carrys out hot update or reload. - Green

2 Answers

2
votes

Hot reloading server middleware bundled with Webpack is actually much easier than hot reloading client side bundles for two reasons:

  1. You don't have to handle server / client communication.
  2. Middleware is almost always necessarily stateless so you don't need to concern yourself with state preservation.

This means you can ignore all the moving parts associated with client side hot module reloading such as WebSockets as well as teaching your code to update itself through module.hot.accept / module.hot.dispose.

Here's an example:

// ./src/middleware.js
module.exports = (req, res) => {
    res.send('Hello World');
};
// webpack.config.js
const path = require('path');

module.exports = {
    target: 'node',
    entry: './src/middleware.js',
    output: {
        path: path.join(__dirname, './dist'),
        filename: 'middleware.js',
        libraryTarget: 'commonjs2'
    }
};
// ./src/index.js
const express = require('express');
const config = require('webpack.config.js');

const app = express();
const queue = [];
let latestMiddleware;

webpack(config).watch(() => {
    // re-require new middleware
    delete require.cache[require.resolve('./dist/middleware.js')]
    latestMiddleware = require('./dist/middleware.js');
    // pass buffered requests to latestMiddleware
    while (queue.length) latestMiddleware.apply(void 0, queue.shift());
});

app.use((req, res, next) => {
    if (latestMiddleware) {
        latestMiddleware(req, res, next);
        return;
    }
    queue.push([req, res, next]);
});

app.listen(6060);

As you can see the fact that there's no state to worry about means the latestMiddleware can simply reference the new bundled middleware without having to write custom logic to update other modules in the dependency graph.

Incidentally, this is the exact same technique used by webpack-hot-server-middleware, the only difference is webpack-hot-server-middleware is more geared towards hot reloading universal apps on the server.

-1
votes