ルートを動的に作成する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をハイジャックすることはありませんか?
@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はどうですか?データベースに送信されるすべてのリクエストで、水平方向のスケーリングが向上します。
実行時にルートを作成または破棄しようとすると、非常に注意が必要です。データ構造は自分で変更できますが、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マッピングを管理します。直接データベースアクセス、キャッシュ+データベースアクセス、またはタイマーベースのリフレッシャーを使用できます。
前述のように、ルートの追加はその場で行うことができます。この機能を考えると、削除も可能です。
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で特定のマップされたルートを削除すると、静的マッピングが削除されますか? )
このようにルートを更新すると、アプリが「ステートフル」になり、負荷分散が必要な場合に問題が発生する可能性があります。