web-dev-qa-db-ja.com

Node.js / Express.js-app.routerの仕組み

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

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

Express.jsアプリケーション(バージョン3.0.0rc4)を作成したとき、コマンドexpress app --sessions --css stylusを使用し、app.jsファイルでexpress.static()の上にapp.routerを含むコードがセットアップされましたおよび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を表示しました。ハハ、OK、app.routerが何をするのかわかりません。コードに含まれているかどうかにかかわらず、ルーティングは問題ありません。だから私は間違いなく何かを見逃しています。

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

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

294
Aust

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


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

たとえば、express.static('/var/www')はそのフォルダ内のファイルを処理します。そのため、http://server/file.htmlをNodeサーバーに要求すると、/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つを上書きできないようにします。

useを明示的にrouterと指定しないと、ルートを定義した時点でExpressによって暗黙的に追加されることに注意してください(app.use(app.router)をコメントアウトしたにもかかわらずルートが引き続き機能する理由です)。


コメントしていなかったstaticrouterの順序について、コメンターが 別の点 を提起しました:あなたのアプリケーションの全体的なパフォーマンスへの影響。

useの上にrouterstaticを追加するもう1つの理由は、パフォーマンスを最適化するためです。最初にstaticを入力すると、ファイルが存在するかどうかを確認するために、要求があるたびにハードドライブにアクセスします。 クイックテスト では、アンロードされたサーバーでこのオーバーヘッドが最大1msになることがわかりました。 (その数は、リクエストがディスクアクセスを奪い合う負荷の下ではもっと高くなる可能性が高いです。

routerを最初に使用すると、ルートに一致する要求がディスクにヒットする必要がなくなり、貴重なミリ秒を節約できます。

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

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

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

この状況では、これをrouterの上に置きます。ファイルが存在する場合、これは他のミドルウェア/ルーターを処理することを避けます、しかし正直に言うと、私はあなたがそんなに得ることは疑います。

また、 staticCache を使用することもできます。これは、静的リソースをメモリ内にキャッシュするため、一般的に要求されるファイルのためにディスクにアクセスする必要はありません。 (警告:staticCacheは今後削除される予定です 。)

しかし、私はstaticCacheが否定的な答えをキャッシュしているとは思いません(ファイルが存在しないとき)ので、staticCacheをパスにマウントせずにrouterより上に置いた場合は役に立ちません。

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


エクスプレス4

Express 4.0app.routerを削除します。すべてのミドルウェア(app.use)および経路(app.get他)は、追加された順番どおりに処理されるようになりました。

言い換えると:

すべてのルーティング方法は、表示されている順序で追加されます。あなたは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での変更点についてもっと読む

328
josh3736

ルーティングとは、アプリケーションが特定のエンドポイントへのクライアント要求にどのように応答するかを決定することを意味します。これは、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')
})
2
Parth Raval

エクスプレスバージョン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.jsでは、route.jsファイルのルーターオブジェクトをインポートし、それをserver.jsに次のように適用しました。

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

これで、route.js内のすべての経路は以下のベースURLを持ちます。

http:// localhost:3000/route

なぜこのアプローチが:

このアプローチをとることの主な利点は今私達のアプリがより多くのモジュラーであるということです。特定のルートのすべてのルートハンドラを異なるファイルに保存できるようになりました。これにより、すべてのファイルの保守性が向上し、検索が容易になります。

0