2013-03-11 2 views
13

동적으로 경로를 만드는 express.js로 간단한 CMS를 만들려고합니다.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'} 
    } 
} 

및 반복과 같이 경로를 만드는 개체 이상 :

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

이제 모든 것이 제대로 작동 그것은 다음과 같습니다 데이터베이스에서 JSON을 가져옵니다. 하지만 문제는 사용자가 콘텐츠와 경로를 수정할 때마다 전체 노드 앱을 다시 시작해야한다는 것입니다. 경로를 제거하기 위해 API 호출을 찾지 못했습니다.

app.get으로 설정된 이전 경로를 안전하게 제거 할 수있는 방법이 있습니까? 나는 그 일을해야합니까?

이런 종류의 라우팅을 수행하는 더 좋은 방법이 있습니까? 내가 내장 된 함수를 사용할 수있게 해주는이 메소드가 마음에 들지만, 빠르며 정규 표현식을 지원한다.

app.routes = nul을 사용하여 전체 app.routes를 제거하려고 시도했지만 아무 것도하지 않았으므로 기존 경로가 그대로 유지되었습니다. 실제로 제거 않았다

한 가지

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

이었다 그러나 이것은 실제로 제거 않으며, 그렇게 사용하는 라우터가 다시 채워지고 계속하면 나는 숫양의 엄청난 양을 납치 결국하지 않는 안전합니까?

+2

AFAIk express는 app._router.map 에있는 모든 경로를 유지하므로 제대로 작동합니다. – supernova

+0

걱정해야 할 렌더링과 관련된 캐시가 있습니까? 또는 바로 아래에 있기 때문에 app._router.map을 사용하여 앱을 제거한 것입니까? 프로덕션 모드에서 –

+1

을 표현하면 캐시는 app.cache [viewname]를 통해 액세스 할 수 있습니다. – supernova

답변

12

@supermova가 의견에서 언급했듯이, 즉석에서 Express를 업데이트 할 수 있습니다. 고려해야 할 또 다른 아키텍처는 클래식 CMS와 유사한 아키텍처입니다 (예 : Wordpress와 같은). 다른 CMS에서는 모든 요청이 동일한 '콜백'으로 이동하고 모든 요청이 인 경우 에서 해당 URL에 대해 어떤 페이지를 제공할지 데이터베이스에서 조회합니다.

이 방법의 결과로 속도가 크게 저하되었지만 결국에는 제정신이라고 생각합니다. 속도가 큰 문제라면 캐니스터 (Varnish와 같은)를 설치할 수 있지만 신속한 고속 수정 경로를 사용하는 두통이 있습니다. 예를 들어, 두 개의 웹 서버로 확장해야한다면 어떻게해야할까요? 서버 A가 '페이지 생성'요청을 받고 경로를 업데이트하는 것을 알고 있다면 어떻게 동기화합니까? 서버 B는 어떻게됩니까? 모든 요청이 데이터베이스로 이동하면 수평 확장이 더 잘됩니다.

+0

이미 바니시를 사용하고 있지만 IMO로는 문제를 해결하는 올바른 방법이 아닙니다 ... 동적으로 경로를 만드는 것과 비교할 때 많은 페이지가있을 때 실제로는 끔찍하게 느립니다. –

1

런타임시 경로를 만들거나 파괴하려고 할 때 매우주의해야합니다. 데이터 구조를 직접 변경할 수는 있지만 API로 문서화되어 있다고는 생각하지 않습니다. 따라서 Express를 업그레이드 할 때 이러한 손상이 발생할 위험이 있습니다.

페이지 집합이 얼마나 큰지 누가 알 수 있는지 파악할 수 있기 때문에 각 데이터베이스 개체에 대해 새 경로를 만들면 메모리 제약이 될 수도 있습니다.

이걸보세요 ... 새로운 경로는 필요하지 않습니다. 기존 경로에 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); 
    } 
}); 

와 같은 특정 기능에 URL 패턴을지도 명시 층의 외부 pagesfromdb 매핑을 관리하기 위해 와일드 카드를 사용할 수 있습니다. 직접 수행하는 데이터베이스 액세스, 캐시 + 데이터베이스 액세스 또는 타이머 기반 새로 고침을 사용할 수 있습니다.

+0

이 방법의 문제점은 regexp 기능을 다시 만들어야한다는 것입니다. –

+0

내 첫 번째 질문에 대한 후속 조치. 래퍼를 사용하지 않고 자체적으로 노드 응용 프로그램을 다시 시작할 수있는 방법이 있습니까? –

+0

할 수는 있지만 쉽게 할 수는 없습니다. process.execPath와 process.argv [1]을 사용하여 자신을 시작할 수 있습니다. 하지만 작동 시키려면 먼저 네트워크 소켓을 분리하고 모든 파일의 잠금을 해제해야합니다 ... 일반 리소스 정리. – Brandon

0

경로를 추가하는 것은 언급 한대로 즉시 수행 할 수 있습니다. (Removing a specfic mapped route in Node.js at runtime removes static mapping?에서 도난)

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

이 같은

업데이트 경로가 "상태"귀하의 응용 프로그램을 만들 않으며, 당신은 부하 균형이 필요하면 아마 문제가 발생할 것입니다 : 삭제도이 fuction를 부여 할 수 있습니다.

관련 문제