2013-03-11 4 views
13

Próbuję utworzyć prosty CMS z plikiem express.js, który dynamicznie tworzy trasy. Robi się JSON z bazy danych, która wygląda następująco:Najlepszy sposób na dynamiczne kierowanie za pomocą 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'} 
    } 
} 

i iteracje nad obiektami tworzących trasy tak:

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

Teraz wszystko działa poprawnie. Problem polega jednak na tym, że za każdym razem, gdy użytkownik modyfikuje zawartość i ścieżki, należy zrestartować całą aplikację węzła. Nie znalazłem żadnych wywołań interfejsu API, aby usunąć trasy.

Czy istnieje sposób na bezpieczne usunięcie starego zestawu tras za pomocą aplikacji app.get? Czy powinienem to zrobić?

Czy jest lepszy sposób na robienie tego rodzaju trasowania? Podoba mi się ta metoda, ponieważ pozwala mi korzystać z wbudowanej funkcji, jest szybka i obsługuje regex.

Próbowałem usunąć całą app.routes za pomocą app.routes = nul, ale nic nie dało, stare trasy były nadal na miejscu.

Jedną rzeczą, która rzeczywiście je usunąć był

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

Ale czy to rzeczywiście je usunąć i jest bezpieczny w użyciu, więc nie kończy się porwania ogromne ilości pamięci RAM, czy router staje się coraz odbudowane?

+2

Ekspres AFAIk przechowuje wszystkie trasy w app._router.map , więc to powinno działać. – supernova

+0

Czy są jakieś pamięci podręczne związane z renderowaniem, o które powinienem się martwić. Czy są one po prostu usuwane z app._router.map, ponieważ są one tuż pod nim? –

+1

w trybie ekspresowym widoki pamięci podręcznej, pamięć podręczna jest dostępna za pośrednictwem app.cache [nazwa widoku]. – supernova

Odpowiedz

12

Jak powiedziała @supermova w komentarzach, można zaktualizować Express w locie. Kolejną rozważaną architekturą jest ta, która przypomina klasyczne CMSy (np. Wordpress). W innych CMS wszystkie żądania trafiają do tego samego "wywołania zwrotnego" i do każdego żądaniasprawdzasz w bazie danych, która strona jest wyświetlana dla tego adresu URL.

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

W wyniku tej metody nastąpił znaczny spadek prędkości, ale ostatecznie uważam, że jest bardziej rozsądny. Jeśli szybkość jest olbrzymim problemem, możesz ustawić system buforowania (np. Varnish), ale pojawią się bóle głowy związane z modyfikowaniem tras ekspresowych w locie. Na przykład, co, jeśli musisz skalować do dwóch serwerów internetowych? Jak zachować synchronizację, jeśli serwer A otrzyma żądanie "Utwórz stronę" i zaktualizuje swoje trasy, ale co z serwerem B? Przy każdym zgłoszeniu się do bazy danych będziesz mógł skalować poziomo lepiej.

+0

Używam już lakieru, ale IMO to nie jest właściwe podejście do naprawiania rzeczy ... To jest rzeczywiście strasznie powolne, gdy jest dużo stron w porównaniu do dynamicznego tworzenia tras. –

1

Byłbym bardzo ostrożny, próbując tworzyć lub niszczyć trasy w czasie wykonywania. Chociaż możesz sam zmienić strukturę danych, nie wierzę, że są one udokumentowane jako interfejsy API, więc ryzykujesz tym zerwaniem, jeśli/po aktualizacji Express.

Może to również służyć jako ograniczenie pamięci, jeśli utworzysz nową trasę dla każdego obiektu bazy danych, ponieważ zbiór stron może wzrosnąć do tego, kto wie, jak duży.

Spójrz na to w ten sposób ... nie chcesz nowych tras; chcesz dodać adresy URL do istniejących tras. Jeśli dodajesz trasę, oznacza to, że chcesz, aby jakiś adres URL był mapowany do jakiejś odrębnej funkcji. Ale odwzorowujesz każdy adres URL na tę samą funkcję. Zasadniczo dodajesz tylko trasy efekt uboczny. Tym, na czym Ci zależy, jest dynamiczny zestaw map URL do określonej funkcji.

Zamiast tego można użyć symbolu wieloznacznego mapowania wzorzec URL do określonej funkcji, jak

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

i zarządzać mapowanie pagesfromdb poza wyraźnej warstwy. Możesz korzystać z bezpośredniego dostępu do bazy danych, dostępu do pamięci podręcznej + bazy danych lub odświeżacza opartego na czasomierzu, co jest najlepsze dla Ciebie.

+0

Problem z tą metodą polega na ponownym utworzeniu funkcji regexp. –

+0

Jako kontynuację mojego pierwszego pytania. Czy istnieje sposób na zrestartowanie aplikacji węzła wewnątrz samej siebie bez uciekania się do jakichkolwiek wrapperów? –

+0

Można to zrobić, tak, ale nie jest to łatwe. Możesz uruchomić się przy użyciu process.execPath i process.argv [1]. Ale aby to zadziałało, musisz najpierw rozłączyć wszystkie gniazda sieciowe i odblokować dowolne pliki ... ogólne oczyszczanie zasobów. – Brandon

0

Dodawanie tras można wykonać w locie, jak wspomniano. Usuwanie może też, biorąc pod uwagę to 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); 
    } 
    } 
} 

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

Trasy Aktualizacja jak to robi aplikację „stanowe” i prawdopodobnie doprowadzi do problemów, jeśli trzeba bilans obciążenia.