gpt4 book ai didi

javascript - 使用多个路由时,使用express和chokidar进行热重载会导致http header 发送错误

转载 作者:太空宇宙 更新时间:2023-11-03 23:21:32 25 4
gpt4 key购买 nike

我一直在尝试各种热重载设置,我遇到的一个是 https://github.com/glenjamin/ultimate-hot-reloading-example/ 。以修改此样板代码为起点,我在服务器代码中遇到了以下问题:

// server.js
import chokidar from 'chokidar';
import express from 'express';

const app = express();

// this is the middleware for handline all of my routes
app.use(function (req, res, next) {
require('./server/index')(req, res, next);
// if I commented out any additional routes, the setup would work fine
require('./server/foo')(req, res, next);
require('./server/catch-all')(req, res, next);
});

//this watches the server folder for changes
const watcher = chokidar.watch('./server');

watcher.on('ready', function () {
watcher.on('all', function () {
console.log("Clearing /server/ module cache from server");
Object.keys(require.cache).forEach(function (id) {
if (/[\/\\]server[\/\\]/.test(id)) delete require.cache[id];
});
});
});

app.listen(3000, 'localhost', function (err) {
if (err) throw err;
const addr = this.address();
console.log('Listening at http://%s:%d', addr.address, addr.port);
});

上面是通过监视 chokidar 模块的更改来处理清除缓存的服务器代码。如果我在 app.use 中间件函数(监听每个传入请求)中只需要一条路由,我就可以让它工作。但是如果有多个路由,则会出现以下错误:

错误 [ERR_HTTP_HEADERS_SENT]:将 header 发送到客户端后无法设置 header

这是堆栈溢出上发布的一个常见问题,但我遇到并尝试过的所有解决方案均无效。我的路线文件如下:

//index.js
import express from 'express';

const router = express.Router();

router.get('/', (req, res, next) => {
res.send("greagrehgarhegrehuh").end();
return next('router');
});

module.exports = router;
//end of index.js

//foo.js
import express from 'express';

const router = express.Router();

router.get('/foo', (req, res, next) => {
res.send("foo").end();
return next('router');
});

module.exports = router;
//end of foo.js

//catch-all.js
import express from 'express';

const router = express.Router();

router.get('*', (req, res, next) => {
res.send("catch all").end();
return next('router');
});

module.exports = router;
// end of catch-all.js

除了端点之外,所有三个路由都执行相同的操作。到目前为止,我已经明确地在每个函数上调用 end 来结束响应,使用 return next('router') 来跳过其余的中间件函数,并且也尝试在没有上述函数的情况下执行此操作。关于我在这里缺少什么来让这个工作有什么想法吗?这是一个展示该问题的 github 项目

https://github.com/RonanQuigley/express-chokidar-hot-reload

更新

所以我实际上删除了接下来的调用,并且通过执行以下操作似乎几乎已经使其正常工作:

app.use(function (req, res, next) {
require('./server/index')(req, res, next);
require('./server/foo')(req, res, next);
});

// a second app.use middleware, that does the same
// as the catch all // * router.get from my original post
app.use(function (req, res, next) {
app.get('*', (req, res) => res.send('catch all'));
})

但是,我无法将第二个 app.use 与另一个需要调用具有快速路由器的文件的文件一起使用,就像其他应用程序一样。所以看起来express通过中间件堆栈运行,到达*并尝试设置 header 两次。

我需要 * 的原因通常是,如果用户请求不存在的端点, Node 会正确显示无法获取/。然而,由于某种原因,使用我概述的设置,express 将会崩溃。我的解决方法是在中间件堆栈的末尾使用 * ,我只需使用 res.redirect 将用户发送回任何地方,但这会导致我在原始帖子中概述的上述问题。所以不知道如何解决这个问题。

所以目前我有:

1) 热重载不需要 router.get('*'),但是当用户导航到不存在的端点时,express 将崩溃。

2) 热重载与第二个 app.use 调用中的 app.get('*') 一起使用,但我无法使用路由器将其移动到单独的文件中。

最佳答案

好的,所以发布这个解决方案以供我自己将来引用,以防其他人遇到这个问题。

与 Express 开发人员交谈后,事实证明,通过以下组合确实可以实现这一点:

// you need to use comma separated routes
app.use(
dynamic('./server/index'),
dynamic('./server/foo')
);

// require the library at runtime and apply the req, res, next arguments
function dynamic(lib) {
return function (req, res, next) {
return require(lib).apply(this, arguments)
}
}

对于 webpack,这会破坏它,因为你不能使用 require 作为表达式。因此,请使用以下方法来解决这个问题:

function createRoutes(router) {
const dynamic = (lib) => {
return function (req, res, next) {
// let webpack generate a regex expression from this require
// if we don't you would get a critical dependency warning
// which would result in the routes not being found
return require("./src/" + lib + ".js").apply(this, arguments);
}
}
router.use(
dynamic('index'),
dynamic('foo'),
);
return router;
}

关于javascript - 使用多个路由时,使用express和chokidar进行热重载会导致http header 发送错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49129577/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com