2013-03-11 9 views
13

Ich versuche, ein einfaches CMS mit express.js zu erstellen, das dynamisch Routen erstellt. Es wird eine JSON aus einer Datenbank, die wie folgt aussieht:Die beste Methode für dynamisches Routing mit Express.js (node.js)

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'} 
    } 
} 

und iteriert über die Objekte zu schaffen Routen wie so:

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

Jetzt funktioniert alles einwandfrei. Das Problem ist jedoch, dass jedes Mal, wenn ein Benutzer den Inhalt und die Pfade ändert, die gesamte Knoten-App neu gestartet werden muss. Ich habe keine API-Aufrufe gefunden, um Routen zu entfernen.

Gibt es eine Möglichkeit, die alten Routen, die mit app.get gesetzt wurden, sicher zu entfernen? Soll ich das überhaupt tun?

Gibt es eine bessere Möglichkeit, diese Art von Routing zu tun? Ich mag diese Methode, da sie mir die eingebaute Funktion erlaubt, schnell ist und Regex unterstützt.

Ich habe versucht, die ganze app.routes mit app.routes = nul zu entfernen, aber es hat nichts gemacht, die alten Routen waren immer noch vorhanden.

Eine Sache, die in der Tat, sie haben entfernen war

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

Aber ist diese sie tatsächlich entfernen und ist es sicher zu verwenden, so dass sie am Ende ich nicht große Mengen an RAM Hijacking, wenn der Router hält neu besiedelt zu werden?

+2

AFAIk Express hält alle Routen in App._router.map so sollte dies funktionieren. – supernova

+0

Gibt es Caches im Zusammenhang mit dem Render, um den ich mich sorgen sollte? Oder werden sie nur mit der app._router.map entfernt, da sie gerade darunter liegen? –

+1

im Produktionsmodus Express Caches Ansichten, der Cache kann über app.cache [viewname] zugegriffen werden. – supernova

Antwort

12

Wie @supermova in den Kommentaren sagte, ist es möglich, Express on-the-fly zu aktualisieren. Eine andere Architektur, die in Betracht gezogen wird, ist die, die klassischen CMS ähnlich ist (wie zum Beispiel Wordpress). In anderen CMS gehen alle Anfragen zum gleichen "Rückruf" und auf jede Anfrage Sie in der Datenbank nachschlagen, welche Seite für diese URL dienen soll.

Es gibt eine signifikante Geschwindigkeitsabnahme als Ergebnis dieser Methode, aber am Ende denke ich, dass es vernünftiger ist. Wenn Geschwindigkeit ein großes Problem ist, können Sie ein Caching-System (wie Varnish) einrichten, aber es wird Kopfschmerzen mit dem Ansatz, Express-Routen on-the-fly zu ändern. Was ist zum Beispiel, wenn Sie auf zwei Webserver skalieren müssen? Wie halten Sie sie synchron, wenn der Server A die Anforderung zum Erstellen der Seite erhält und er weiß, dass er seine Routen aktualisieren muss, aber was ist mit Server B? Mit jeder Anfrage in der Datenbank können Sie horizontal besser skalieren.

+0

Ich benutze bereits Varnish, aber IMO ist es nicht der richtige Ansatz, um die Dinge zu reparieren ... Das ist wirklich schrecklich langsam, wenn es viele Seiten im Vergleich zu dynamisch erstellen Routen gibt. –

1

Ich würde sehr vorsichtig versuchen, Routen zur Laufzeit zu erstellen oder zu zerstören. Obwohl Sie die Datenstrukturen selbst ändern können, glaube ich nicht, dass diese als APIs dokumentiert sind. Sie riskieren das, wenn Sie Express aktualisieren.

Dies könnte auch als eine Speicherbeschränkung dienen, wenn Sie eine neue Route für jedes Datenbankobjekt erstellen, da die Menge der Seiten zu wer weiß wie groß wachsen kann.

Schau es so ... du willst keine neuen Routen; Sie möchten URLs zu bestehenden Routen hinzufügen. Wenn Sie eine Route hinzufügen, bedeutet dies, dass Sie möchten, dass eine URL einer bestimmten Funktion zugeordnet wird. Aber Sie ordnen jede URL der gleichen Funktion zu. Im Wesentlichen fügen Sie Routen nur als Nebeneffekt hinzu. Was Ihnen wichtig ist, ist, dass einige dynamische URLs einer bestimmten Funktion zugeordnet sind.

Können Sie stattdessen einen Platzhalter verwenden, um das URL-Muster auf eine bestimmte Funktion abzubilden, wie

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

Und außerhalb der Express-Schicht, die das pagesfromdb Mapping verwalten. Sie können direkten Datenbankzugriff, Cache + Datenbankzugriff oder eine zeitgesteuerte Aktualisierung verwenden, die für Sie am besten geeignet ist.

+0

Das Problem mit dieser Methode ist, dass ich Regexp-Funktionalität neu erstellen muss. –

+0

Als Folge meiner ersten Frage. Gibt es eine Möglichkeit, die Knotenanwendung in sich selbst neu zu starten, ohne auf Wrapper zuzugreifen? –

+0

Es kann getan werden, ja, aber nicht leicht. Sie können sich selbst starten, indem Sie process.execPath und process.argv [1] verwenden. Damit das funktioniert, müssen Sie zuerst alle Netzwerk-Sockets trennen und alle Dateien entsperren ... allgemeine Ressourcenbereinigung. – Brandon

0

Hinzufügen von Routen kann im laufenden Betrieb erfolgen, wie bereits erwähnt. Löschen zu können, dieses fuction gegeben:

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

(bestohlen Removing a specfic mapped route in Node.js at runtime removes static mapping?)

Updating Routen wie diese machen die App „Stateful“, und werden wahrscheinlich zu einem Problem führen, wenn Sie Lastausgleich benötigen.

Verwandte Themen