Подтвердить что ты не робот

Лучший способ динамической маршрутизации с помощью Express.js(node.js)

Я пытаюсь создать простую CMS с express.js, которая динамически создает маршруты. Он получает 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]);
    });
});

Теперь все работает нормально. Но проблема заключается в том, что каждый раз, когда пользователь изменяет содержимое и пути, все приложение node необходимо перезапустить. Я не нашел никаких вызовов API для удаления маршрутов.

Есть ли способ безопасно удалить старые маршруты, установленные с app.get? Должен ли я это сделать?

Есть ли лучший способ сделать такую ​​маршрутизацию? Мне нравится этот метод, так как он позволяет мне использовать встроенную функцию, быстро и поддерживает регулярное выражение.

Я попытался удалить все app.routes с помощью app.routes = nul, но ничего не сделал, старые маршруты все еще были на месте.

Одна вещь, которая действительно удалила их, была

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

Но действительно ли это удаляет их, и безопасно ли это использовать, поэтому я не могу захватить огромное количество бара, если маршрутизатор продолжает переполняться?

4b9b3361

Ответ 1

Как поясняет @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 на лету. Например, что делать, если вам нужно масштабировать до двух веб-серверов? Как вы храните их в синхронизации, если сервер A получает запрос "создать страницу", и поэтому он знает, как обновлять маршруты, но как насчет сервера B? С каждым запросом, отправляющимся в базу данных, вы сможете масштабировать горизонтально лучше.

Ответ 2

Я бы очень старался создавать или уничтожать маршруты во время выполнения. Хотя вы можете сами изменить структуры данных, я не считаю, что они документированы как 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);
    }
});

И управляйте отображением pagesfromdb вне экспресс-слоя. Вы можете использовать прямой доступ к базе данных, кэш + доступ к базе данных или обновить таймер, независимо от того, что лучше всего подходит вам.

Ответ 3

Добавление маршрутов может выполняться "на лету", как уже упоминалось. Удаление может также, учитывая это fuction:

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);
    }
  }
}

(украден из Удаление specfic сопоставленного маршрута в Node.js во время выполнения удаляет статическое сопоставление?)

Обновление таких маршрутов делает ваше приложение "stateful" и, вероятно, приведет к возникновению проблем, если вам нужен баланс нагрузки.