15

我正在尝试使用 express.js 创建一个简单的 CMS,它可以动态创建路由。它从如下所示的数据库中获取 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'}
    }
}

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

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

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

有什么方法可以安全地删除用 app.get 设置的旧路线?我应该这样做吗?

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

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

确实删除它们的一件事是

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

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

4

3 回答 3

16

正如@supermova 在评论中所说,可以即时更新 Express。要考虑的另一种架构是类似于经典 CMS(例如 Wordpress)的架构。在其他 CMS 中,所有请求都转到相同的“回调”,并且在每个请求中,您都在数据库中查找为该 URL 服务的页面。

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

这种方法导致速度显着降低,但最后我认为它更理智。如果速度是一个大问题,您可以设置一个缓存系统(如 Varnish),但是动态修改 Express 路线的方法会让人头疼。例如,如果您必须扩展到两个 Web 服务器怎么办?如果服务器 A 收到“创建页面”请求并且知道要更新其路由,那么如何使它们保持同步,但是服务器 B 呢?随着每个请求进入数据库,您将能够更好地水平扩展。

于 2013-03-12T20:07:36.587 回答
1

我会非常小心地尝试在运行时创建或销毁路由。尽管您可以自己更改数据结构,但我不认为这些被记录为 API,因此如果/当您升级 Express 时,您可能会面临破坏的风险。

如果您为每个数据库对象创建一个新路由,这也可以作为内存约束,因为页面集可能会增长到不知道有多大。

像这样看……你不想要新路线;您想将 URL 添加到现有路由。如果要添加路由,则意味着您希望某个 URL 映射到某个不同的功能。但是您将每个 URL 映射到相同的函数。本质上,您只是通过副作用添加路线。你关心的是一些动态的 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);
    }
});

并在 express 层之外管理 pagesfromdb 映射。您可以使用直接数据库访问、缓存 + 数据库访问或基于计时器的刷新,无论哪种方式最适合您。

于 2013-03-12T20:22:02.810 回答
0

如前所述,可以即时添加路线。鉴于此功能,删除也可以:

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 中的特定映射路由删除静态映射?

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

于 2015-03-03T10:06:52.587 回答