web-dev-qa-db-ja.com

Express.js(node.js)で動的ルーティングを行うための最良の方法

ルートを動的に作成する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全体を削除しようとしましたが、何も実行されず、古いルートは引き続き使用されていました。

実際にそれらを削除した1つのことは

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

しかし、これは実際にそれらを削除し、使用しても安全なので、ルーターが再投入され続けても大量のRAMをハイジャックすることはありませんか?

14

@supermovaがコメントで述べたように、Expressをオンザフライで更新することは可能です。考慮すべきもう1つのアーキテクチャは、従来の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ルートをオンザフライで変更するアプローチには頭痛の種があります。たとえば、2つのWebサーバーに拡張する必要がある場合はどうなりますか?サーバーAが「ページの作成」要求を受け取り、ルートを更新することを認識している場合、どのようにそれらを同期させますか?サーバーBはどうですか?データベースに送信されるすべてのリクエストで、水平方向のスケーリングが向上します。

14
Max

実行時にルートを作成または破棄しようとすると、非常に注意が必要です。データ構造は自分で変更できますが、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マッピングを管理します。直接データベースアクセス、キャッシュ+データベースアクセス、またはタイマーベースのリフレッシャーを使用できます。

1
Brandon

前述のように、ルートの追加はその場で行うことができます。この機能を考えると、削除も可能です。

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で特定のマップされたルートを削除すると、静的マッピングが削除されますか?

このようにルートを更新すると、アプリが「ステートフル」になり、負荷分散が必要な場合に問題が発生する可能性があります。

0
Albin