使用Express.js(node.js)进行dynamic路由的最佳方法

我试图创build一个简单的CMS与express.jsdynamic地创build路线。 它从数据库中获取JSON,如下所示:

pagesfromdb = { home = { paths = ['/','/home','/koti'], render = 'home.ejs', fi_FI = {html='<h1>Hei maailma!</h1>'}, en_US = {html='<h1>Hello World!</h1>'} }, about = { paths = ['/about','/tietoja'], render = 'general.ejs', fi_FI = {html='Tietoja'}, en_US = {html='About Us'} } } 

并迭代创build路由的对象,如下所示:

 Object.keys(pagesfromdb).forEach(function(key) { var page = pagesfromdb[key]; app.get(page.global.paths,function(req, res){ res.render(page.render, page[language]); }); }); 

现在一切正常。 但问题是,每当用户修改内容和path时,整个节点应用程序都需要重新启动。 我没有find任何API调用来删除路由。

有没有办法安全地删除app.get设置的旧路线? 我应该这样做吗?

有没有更好的方法来做这种路由? 我喜欢这种方法,因为它允许我使用内置函数,速度快,支持正则expression式。

我尝试删除app.routes = nul整个app.routes,但它没有做任何事情,旧的路线仍然在位。

有一件事确实消除了他们

 delete app._router.map.get; app._router.map.get = []; 

但是,这实际上是否删除它们,是否安全使用,所以我不会最终劫持大量的内存,如果路由器不断重新填充?

正如@supermova在评论中所说,可以在即时更新Express。 另一个需要考虑的架构是类似于经典的CMS(比如Wordpress)。 在其他CMS中,所有请求都会进行相同的“callback”,并在每个请求中查找数据库中的哪个页面。

 app.get('/*', function (req, res) { db.findPage({ slug: req.url}, function (err, pageData) { res.render('page-template', { pageContent: pageData.content, pageTitle: pageData.title }); }); }); 

这种方法导致速度显着下降,但最终我觉得更为理智。 如果速度是一个巨大的问题,你可以build立一个caching系统(如Varnish),但是在快速修改Express路线方面会遇到麻烦。 例如,如果您必须扩展到两个Web服务器,该怎么办? 如果服务器A获取“创build页面”请求,并且知道更新它的路由,那么如何使它们保持同步,但服务器B又如何呢? 随着每个请求到数据库,你将能够水平扩展更好。

尝试在运行时创build或销毁路由时,我会非常小心。 虽然你可以自己改变数据结构,但是我不认为这些API被logging为API,所以如果/升级Express的话,你可能会冒这个风险。

如果你为每个数据库对象创build一个新的路由,这也可以作为一个内存约束,因为这组页面可以增长到谁知道有多大。

看看这样…你不想要新的路线; 你想添加URL到现有的路由。 如果你添加一个路由,这意味着你想要一些URL映射到一个独特的function。 但是你将每个URL映射到相同的function。 实质上,你只是通过副作用添加路线。 你关心的是一些dynamic的URL映射到一个特定的函数。

你可以使用通配符将URL模式映射到特定的函数,比如

 app.get('/pages/*', function(req, res) { var page = pagesfromdb[key]; if (page != null) { res.render(page.render, page.language) } else { res.send(404); } }); 

并pipe理快速图层以外的pagesfromdb映射。 您可以使用直接的数据库访问,caching+数据库访问或基于计时器的刷新,无论哪个最适合您。

如上所述,添加路线可以在飞行中完成。 删除也可以,因为这个function:

 function deleteRoute(url) { for (var i = app.routes.get.length - 1; i >= 0; i--) { if (app.routes.get[i].path === "/" + url) { app.routes.get.splice(i, 1); } } } 

( 在运行时从Node.js中删除特定的映射路由会删除静态映射? )

像这样更新路由会使您的应用“有状态”,并且如果您需要负载均衡,可能会导致问题。