Node.js / Express.js-app.routerはどのように機能しますか?


298

質問する前にapp.router、少なくともミドルウェアを使用しているときに何が起こると思うかについて説明する必要があると思います。ミドルウェアを使用するには、使用する機能はapp.use()です。ミドルウェアの実行中は、次のミドルウェアを使用して呼び出すか、next()ミドルウェアが呼び出されないようにします。つまり、一部のミドルウェアは他のミドルウェアに依存しており、最後の部分のミドルウェアは呼び出されない場合があるため、ミドルウェアを呼び出す順序は重要です。

今日、私は自分のアプリケーションに取り組んでおり、サーバーをバックグラウンドで実行していました。変更を加えてページを更新し、変更をすぐに確認したいと思っていました。具体的には、レイアウトを変更していました。私はそれを動作させることができなかったので、答えを求めてスタックオーバーフローを検索し、この質問を見つけました。それexpress.static()が下にあることを確認するように言っていますrequire('stylus')。しかし、そのOPのコードを見ているとapp.router、ミドルウェアの呼び出しの最後に彼の呼び出しがあることがわかりました。その理由を理解しようとしました。

Express.jsアプリケーション(バージョン3.0.0rc4)を作成したとき、コマンドを使用express app --sessions --css stylusし、app.jsファイルで、app.router上記のexpress.static()require('stylus')呼び出しの両方でコードがセットアップされました。したがって、すでにそのように設定されている場合は、そのままにしておく必要があります。

スタイラスの変更を確認できるようにコードを並べ替えると、次のようになります。

app.configure(function(){
  //app.set() calls
  //app.use() calls
  //...
  app.use(app.router);
  app.use(require('stylus').middleware(__dirname + '/public'));
  app.use(express.static(__dirname + '/public', {maxAge: 31557600000}));
});

app.get('/', routes.index);

app.get('/test', function(req, res){
  res.send('Test');
});

そのため、最初のステップはapp.router、コードに含めることの重要性を明らかにすることだと判断しました。だから私はそれをコメントアウトし、私のアプリを起動してに移動しました/。それは私のインデックスページをうまく表示しました。うーん、たぶんうまくいきました。ルートファイル(routes.index)からルーティングをエクスポートしたためです。それで次にナビゲートする/testと、画面にTestが表示されました。はは、わかりましたapp.router。何ができるかわかりません。コードに含まれているかどうかにかかわらず、ルーティングは問題ありません。だから私は間違いなく何かを逃しています。

だからここに私の質問があります:

誰かが何をするかapp.router、その重要性、そしてミドルウェア呼び出しのどこに配置するべきかを説明してもらえますか?また、について簡単な説明をいただければ幸いですexpress.static()。私の知る限りでexpress.static()は、私の情報のキャッシュであり、アプリケーションが要求されたページを見つけることができない場合、キャッシュをチェックして、存在するかどうかを確認します。


18
この質問をしていただきありがとうございます。私はこの答え(そしてそれを促す質問)を見つけるために探し回っています。
Hari Seldon、

8
それは本当によく書かれた質問でした、私は同じことをググっていました。
Kirn

回答:


329

注:これは、バージョン2および3でExpressがどのように機能したかを示しています。Express4については、この投稿の最後を参照してください。


static単にディスクからファイル(静的リソース)を提供します。パス(マウントポイントと呼ばれることもあります)を指定すると、そのフォルダー内のファイルが提供されます。

たとえばexpress.static('/var/www')、そのフォルダ内のファイルを提供します。以下のためのあなたのノードサーバに要求ので、http://server/file.html役立つであろう/var/www/file.html

routerルートを実行するコードです。実行app.get('/user', function(req, res) { ... });すると、router実際にコールバック関数を呼び出してリクエストを処理します。

物事を渡すapp.use順序によって、各ミドルウェアにリクエストを処理する機会が与えられる順序が決まります。たとえばtest.html、静的フォルダーとルートに呼び出されたファイルがある場合:

app.get('/test.html', function(req, res) {
    res.send('Hello from route handler');
});

どれが要求するクライアントに送信されますhttp://server/test.htmlか?use最初に与えられるミドルウェア。

これを行う場合:

app.use(express.static(__dirname + '/public'));
app.use(app.router);

次に、ディスク上のファイルが提供されます。

逆にすると

app.use(app.router);
app.use(express.static(__dirname + '/public'));

次に、ルートハンドラーがリクエストを取得し、「Hello from route handler」がブラウザーに送信されます。

通常、あなたは、ルータを置きたいの上に誤って名前のファイルは、あなたのルートの1つを上書きすることができないように、静的なミドルウェア。

あなたが明示的にいない場合ことを注意、それは暗黙のうちにあなたが(あなたのルートがまだ働いていた、なぜあなたはコメントアウトにもかかわらず、あるルートを定義する時点でエクスプレスによって追加されます)。userouterapp.use(app.router)


コメンターがいる育ての順序については、別のポイントstaticrouter、アプリケーションの全体的なパフォーマンスに影響を与える:私は対処していなかったことを。

use router上記のもう1つの理由staticは、パフォーマンスを最適化することです。static最初に置くと、すべてのリクエストでハードドライブにアクセスして、ファイルが存在するかどうかを確認します。では簡単なテスト、私は、このオーバーヘッドが無負荷のサーバー上の〜1msのに達したことがわかりました。(この数は、負荷がかかると高くなる可能性が高く、ディスクアクセスを求める要求が競合します。)

ではrouterまず、ルートに一致する要求は、貴重なミリ秒を保存する、ディスクをヒットする必要がありません。

もちろん、staticのオーバーヘッドを軽減する方法はいくつかあります。

最善のオプションは、すべての静的リソースを特定のフォルダーの下に置くことです。(IE /static)次にstatic、そのパスにマウントして、パスが次で始まる場合にのみ実行されるようにすることができます/static

app.use('/static', express.static(__dirname + '/static'));

この状況では、これを上に置きますrouter。これにより、ファイルが存在する場合に他のミドルウェアやルーターの処理が回避されますが、正直なところ、それほど多くのことは得られないでしょう。

またstaticCache、静的リソースをメモリ内にキャッシュするを使用することもできます。これにより、一般的に要求されるファイルのディスクをヒットする必要がなくなります。(警告: 将来的にはstaticCache 削除される予定です。)

ただし、staticCache(ファイルが存在しない場合)否定的な回答をキャッシュするとは思わないため、パスにマウントせずにstaticCache上に配置した場合は役に立ちませんrouter

パフォーマンスに関するすべての質問と同様に、実際のアプリケーション(負荷がかかっている状態)を測定およびベンチマークして、ボトルネックが実際にどこにあるかを確認します。


エクスプレス4

Express 4.0 はを削除し app.routerます。すべてのミドルウェア(app.use)とルート(app.getet al)は、追加された順序で正確に処理されるようになりました。

言い換えると:

すべてのルーティングメソッドは、出現順に追加されます。すべきでないapp.use(app.router)。これにより、Expressで最も一般的な問題が解消されます。

言い換えれば、ミキシングapp.use()app[VERB]()は、呼び出された順序で正確に機能します。

app.get('/', home);
app.use('/public', require('st')(process.cwd()));
app.get('/users', users.list);
app.post('/users', users.create);

Express 4の変更点の詳細をご覧ください。


2
router一つの場所に行きます。初めて電話をかけたときapp.get(またはpost他の人が電話をかけたとき)、まだused app.routerになっていない場合は、Expressが追加します。
josh3736 2012年

4
@MikeCauser:いいえ。ディスクアクセスのオーバーヘッド(ファイルが存在するかどうかを確認するため)は、関数呼び出しのオーバーヘッドよりも大きいためです。私のテストでは、そのオーバーヘッドはアンロードされたサーバーで1ミリ秒に達しました。これは、要求がディスクアクセスをめぐって競合する負荷のかかった状態で高くなる可能性が高くなります。staticした後router、それがあるため、他のミドルウェアについての質問には無関係になりしなければならないルータを超えること。
josh3736 2013

2
素晴らしい説明!どうもありがとうございます!
キルン

3
app.routerされて削除されます、現在のマスターブランチに急行-4.0。各ルートは個別のミドルウェアになります。
yanychar 14

3
私がこれで作業するときのもう一つの明確化。Express 4では、ルーターに複数のルートを割り当てることができます。ルーターを使用するには、ルーターにルートパスを指定し、app.use(path、router)を介して「ミドルウェア」スタックに配置します。これにより、それぞれに関連するルートが独自のルーターを使用し、ユニットとしてベースパスを割り当てることができます。私がそれをよりよく理解していれば、別の答えを投稿することを提案します。繰り返しになりますが、scotch.io / tutorials / javascript /…
Joe Lapp

2

ルーティングとは、URI(またはパス)および特定のHTTPリクエストメソッド(GET、POSTなど)である特定のエンドポイントへのクライアントリクエストにアプリケーションがどのように応答するかを決定することです。各ルートには、ルートが一致したときに実行される1つ以上のハンドラー関数を含めることができます。

Express 4.0ルーターでは、これまでよりも柔軟にルートを定義できます。

express.Router()は、ルートのグループを定義するために複数回使用されます。

リクエストを処理するためのミドルウェアとして使用されるルート。

「.param()」を使用してパラメーターを検証するためのミドルウェアとして使用されるルート。

ルート上の複数のリクエストを定義するためのルーターへのショートカットとして使用されるapp.route()

app.route()を使用している場合は、アプリをそのルーターに接続します。

var express = require('express'); //used as middleware
var app = express(); //instance of express.
app.use(app.router);
app.use(express.static(__dirname + '/public')); //All Static like [css,js,images] files are coming from public folder
app.set('views',__dirname + '/views'); //To set Views
app.set('view engine', 'ejs'); //sets View-Engine as ejs
app.engine('html', require('ejs').renderFile); //actually rendering HTML files through EJS. 
app.get('/', function (req, res) {
  res.render('index');  
})
app.get('/test', function (req, res) {
  res.send('test')
})

0

Express Version 4では、次の方法でルートを簡単に定義できます。

server.js:

const express = require('express');
const app = express();
const route = require('./route');

app.use('/route', route);
// here we pass in the imported route object

app.listen(3000, () => console.log('Example app listening on port 3000!'));

route.js:

const express = require('express');
const router = express.Router();

router.get('/specialRoute', function (req, res, next) {
     // route is now http://localhost:3000/route/specialRoute
});

router.get('/', function (req, res, next) {
    // route is now http://localhost:3000/route
});

module.exports = router;

ではserver.jsroute.jsファイルのルーターオブジェクトをインポートし、次のように適用しますserver.js

app.use('/route', route);

これで、すべてのルートのroute.jsベースURLは次のようになります。

http:// localhost:3000 / route

なぜこのアプローチ:

このアプローチの主な利点は、アプリがよりモジュール化されていることです。特定のルートのすべてのルートハンドラーを別のファイルに入れることができるようになり、すべてが保守しやすくなり、見つけやすくなりました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.