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)
Hot reloading server middleware bundled with Webpack is actually much easier than hot reloading client side bundles for two reasons:
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With