服务器代码中的 Webpack 热模块替换 [英] Webpack hot module replacement in server code

查看:34
本文介绍了服务器代码中的 Webpack 热模块替换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

到目前为止,我看过的所有 webpack 示例都涉及客户端热模块替换,例如:这个这个.

根据 webpack 文档,可以使用 webpack-dev-server 或中间件(webpack-dev-webpack-dev-middleware 和 webpack-hot-middleware,以及 webpack-hot-middleware/client 在配置 entry 中,并集成到例如 express js) 中以启用客户端代码的热模块替换

是否可以为服务器端代码启用热模块更换?该文档确实显示了一个 example

var requestHandler = require("./handler.js");var server = require("http").createServer();server.on("request", requestHandler);服务器.听(8080);//检查 HMR 是否启用如果(模块.热){//接受依赖更新module.hot.accept("./handler.js", function() {//替换服务器的请求处理程序server.removeListener("request", requestHandler);requestHandler = require("./handler.js");server.on("request", requestHandler);});}

该文档的解释相当冗长.

那么问题来了,如何在不重启服务器的情况下在服务器端代码中实现模块热替换?(目前,我有 nodemon 监视服务器端代码以在文件更改时重新启动服务器)

解决方案

与 Webpack 捆绑的热重载服务器中间件实际上比热重载客户端包容易得多,原因有两个:

  1. 您不必处理服务器/客户端通信.
  2. 中间件几乎总是无状态的,因此您无需担心状态保存.

这意味着您可以忽略与客户端热模块重新加载相关的所有活动部分,例如 WebSockets,以及通过 module.hot.accept/module 教您的代码自我更新.hot.dispose.

这是一个例子:

//./src/middleware.jsmodule.exports = (req, res) =>{res.send('Hello World');};

//webpack.config.jsconst path = require('path');模块.出口 = {目标:'节点',条目:'./src/middleware.js',输出: {路径:path.join(__dirname, './dist'),文件名:'middleware.js',图书馆目标:'commonjs2'}};

//./src/index.jsconst express = require('express');const config = require('webpack.config.js');const app = express();常量队列 = [];让最新的中间件;webpack(config).watch(() => {//重新需要新的中间件删除 require.cache[require.resolve('./dist/middleware.js')]latestMiddleware = require('./dist/middleware.js');//将缓冲的请求传递给 latestMiddlewarewhile (queue.length) latestMiddleware.apply(void 0, queue.shift());});app.use((req, res, next) => {如果(最新的中间件){最新的中间件(请求,资源,下一个);返回;}queue.push([req, res, next]);});应用程序听(6060);

如您所见,无需担心状态意味着latestMiddleware 可以简单地引用新的捆绑中间件,而无需编写自定义逻辑来更新依赖图中的其他模块.>

顺便说一句,这与 webpack-hot-server 使用的技术完全相同-middleware,唯一的区别是 webpack-hot-server-middleware 更适合在服务器上热重载通用应用程序.

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:

  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.

这篇关于服务器代码中的 Webpack 热模块替换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆