Node.js / Express.js - Bagaimana cara kerja app.router?

298

Sebelum saya bertanya, app.routersaya pikir saya harus menjelaskan setidaknya apa yang saya pikir terjadi ketika bekerja dengan middleware. Untuk menggunakan middleware, fungsi yang digunakan adalah app.use(). Ketika middleware dieksekusi, ia akan memanggil middleware berikutnya dengan menggunakan next()atau membuatnya sehingga tidak ada lagi middleware yang dipanggil. Itu berarti bahwa urutan di mana saya melakukan panggilan middleware saya adalah penting, karena beberapa middleware tergantung pada middleware lain, dan beberapa middleware di bagian akhir bahkan mungkin tidak dipanggil.

Hari ini saya mengerjakan aplikasi saya dan menjalankan server saya di latar belakang. Saya ingin membuat beberapa perubahan dan menyegarkan halaman saya dan segera melihat perubahannya. Secara khusus, saya membuat perubahan pada tata letak saya. Saya tidak bisa membuatnya bekerja sehingga saya mencari Stack Overflow untuk jawabannya dan menemukan pertanyaan ini . Dikatakan untuk memastikan itu express.static()ada di bawah require('stylus'). Tetapi ketika saya melihat kode OP itu, saya melihat bahwa dia memiliki app.routerpanggilannya di akhir panggilan middleware-nya, dan saya mencoba mencari tahu mengapa itu terjadi.

Ketika saya membuat aplikasi Express.js saya (versi 3.0.0rc4), saya menggunakan perintah express app --sessions --css stylusdan dalam file app.js saya kode setup dengan app.routerkedua atas express.static()dan require('stylus')panggilan saya. Jadi sepertinya, jika sudah diatur seperti itu, maka harus tetap seperti itu.

Setelah mengatur ulang kode saya sehingga saya dapat melihat perubahan Stylus saya, tampilannya seperti ini:

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

Jadi saya memutuskan bahwa langkah pertama adalah mencari tahu mengapa penting untuk memiliki app.routerkode saya. Jadi saya berkomentar, memulai aplikasi saya dan menavigasi ke /. Ini menampilkan halaman indeks saya dengan baik. Hmm, mungkin berhasil karena saya mengekspor rute dari file rute saya (routes.index). Jadi selanjutnya saya menavigasi ke /testdan itu ditampilkan Uji di layar. Haha, oke, saya tidak tahu apa app.router. Apakah itu termasuk dalam kode saya atau tidak, rute saya baik-baik saja. Jadi saya pasti kehilangan sesuatu.

Jadi Inilah Pertanyaan Saya:

Bisakah seseorang tolong jelaskan apa app.routeryang penting, pentingnya, dan di mana saya harus meletakkannya di panggilan middleware saya? Akan lebih baik jika saya mendapat penjelasan singkat tentang express.static(). Sejauh yang saya tahu, express.static()adalah cache informasi saya, dan jika aplikasi tidak dapat menemukan halaman yang diminta, itu akan memeriksa cache untuk melihat apakah ada.

Aust
sumber
18
Terima kasih telah mengajukan pertanyaan ini. Saya telah googling di sekitar untuk menemukan jawaban ini (dan pertanyaan untuk menanyakannya).
Hari Seldon
8
Itu pertanyaan yang ditulis dengan sangat baik, saya mencari hal yang sama di Google.
Kirn

Jawaban:

329

Catatan: Ini menjelaskan cara kerja Express di versi 2 dan 3. Lihat akhir posting ini untuk informasi tentang Express 4.


statichanya melayani file ( sumber daya statis ) dari disk. Anda memberikan path (kadang-kadang disebut titik mount), dan melayani file dalam folder itu.

Misalnya, express.static('/var/www')akan melayani file dalam folder itu. Jadi permintaan ke server Node Anda untuk http://server/file.htmlmelayani /var/www/file.html.

routeradalah kode yang menjalankan rute Anda. Ketika Anda melakukannya app.get('/user', function(req, res) { ... });, itu routeryang benar-benar memanggil fungsi panggilan balik untuk memproses permintaan.

Urutan yang Anda berikan untuk app.usemenentukan urutan setiap middleware diberikan kesempatan untuk memproses permintaan. Misalnya, jika Anda memiliki file yang dipanggil test.htmldi folder statis dan rute:

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

Yang mana yang dikirim ke klien yang meminta http://server/test.html? Apapun middleware yang diberikan useterlebih dahulu.

Jika kamu melakukan ini:

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

Kemudian file pada disk disajikan.

Jika Anda melakukannya dengan cara lain,

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

Kemudian pengendali rute mendapat permintaan, dan "Halo dari pengendali rute" dikirim ke browser.

Biasanya, Anda ingin meletakkan router di atas middleware statis sehingga file yang diberi nama tidak sengaja tidak dapat menimpa salah satu rute Anda.

Perhatikan bahwa jika Anda tidak secara eksplisit useyang router, secara implisit ditambahkan dengan Express pada titik Anda mendefinisikan sebuah rute (yang mengapa rute Anda masih bekerja meskipun Anda komentar app.use(app.router)).


Seorang komentator telah mengemukakan poin lain tentang urutan staticdan routeryang belum saya bahas: dampaknya pada kinerja keseluruhan aplikasi Anda.

Alasan lain di use routeratas staticadalah untuk mengoptimalkan kinerja. Jika Anda menempatkan staticdulu, maka Anda akan menekan hard drive pada setiap permintaan tunggal untuk melihat apakah ada file atau tidak. Dalam tes cepat , saya menemukan bahwa overhead ini berjumlah ~ 1 ms pada server yang diturunkan. (Angka itu kemungkinan besar akan lebih tinggi di bawah beban, di mana permintaan akan bersaing untuk akses disk.)

Dengan yang routerpertama, permintaan yang cocok dengan rute tidak perlu mengenai disk, menghemat milidetik berharga.

Tentu saja, ada cara untuk mengurangi staticbiaya overhead.

Pilihan terbaik adalah meletakkan semua sumber daya statis Anda di bawah folder tertentu. (IE /static) Anda kemudian dapat me static- mount ke jalur itu sehingga hanya berjalan ketika jalan dimulai dengan /static:

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

Dalam situasi ini, Anda akan meletakkan ini di atas router. Ini menghindari pemrosesan middleware / router lain jika ada file, tapi jujur, saya ragu Anda akan mendapatkan sebanyak itu.

Anda juga dapat menggunakan staticCache, yang menyimpan sumber daya statis di dalam memori sehingga Anda tidak perlu menekan disk untuk file yang biasa diminta. ( Peringatan: staticCache tampaknya akan dihapus di masa mendatang.)

Namun, saya tidak berpikir staticCachecache jawaban negatif (ketika file tidak ada), jadi tidak membantu jika Anda telah meletakkan di staticCacheatas routertanpa memasangnya ke jalan.

Seperti halnya semua pertanyaan tentang kinerja, ukur dan patok aplikasi dunia nyata Anda (sedang dimuat) untuk melihat di mana sebenarnya hambatannya.


Express 4

Express 4.0 menghapus app.router . Semua middleware ( app.use) dan rute ( app.getet al) sekarang diproses secara tepat sesuai urutan penambahannya.

Dengan kata lain:

Semua metode perutean akan ditambahkan sesuai urutan kemunculannya. Anda seharusnya tidak melakukannya app.use(app.router). Ini menghilangkan masalah paling umum dengan Express.

Dengan kata lain, mencampur app.use()dan app[VERB]()akan bekerja persis sesuai urutan pemanggilannya.

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

Baca lebih lanjut tentang perubahan dalam Express 4.

josh3736
sumber
2
The routerberjalan di satu tempat. Jika, pertama kali Anda menelepon app.get( postatau orang lain), Anda belum used app.router, Express menambahkannya untuk Anda.
josh3736
4
@ MikeCauser: Tidak, karena overhead dari akses disk (untuk melihat ada atau tidaknya file) lebih besar daripada overhead dari pemanggilan fungsi. Dalam pengujian saya , overhead itu berjumlah 1 ms pada server yang diturunkan. Itu kemungkinan jauh lebih tinggi di bawah beban, di mana permintaan akan bersaing untuk akses disk. Dengan staticsetelah itu router, pertanyaan tentang middleware lain menjadi tidak relevan karena harus di atas router.
josh3736
2
Penjelasan luar biasa! Terima kasih banyak!
Kirn
3
app.routeradalah dihapus di cabang master saat ini, yang akan mengungkapkan-4.0 . Setiap rute menjadi middleware terpisah.
yanychar
3
Satu klarifikasi lagi, ketika saya bekerja dengan ini. Dalam express 4, beberapa rute dapat ditugaskan ke router, dan kemudian untuk menggunakan router, router diberikan jalur root dan ditempatkan di tumpukan "middleware" melalui app.use (path, router). Hal ini memungkinkan rute terkait untuk masing-masing menggunakan router mereka sendiri dan ditugaskan jalur dasar sebagai satu unit. Jika saya memahaminya dengan lebih baik, saya akan menawarkan untuk mengirim jawaban lain. Sekali lagi, saya mendapatkan ini dari scotch.io/tutorials/javascript/…
Joe Lapp
2

Routing berarti menentukan bagaimana aplikasi merespons permintaan klien ke titik akhir tertentu, yang merupakan URI (atau jalur) dan metode permintaan HTTP khusus (GET, POST, dan sebagainya). Setiap rute dapat memiliki satu atau lebih fungsi handler, yang dieksekusi ketika rute tersebut cocok.

Di Express 4.0 Router, kami diberi lebih banyak fleksibilitas daripada sebelumnya dalam menentukan rute kami.

express.Router () digunakan beberapa kali untuk menentukan grup rute.

rute yang digunakan sebagai middleware untuk memproses permintaan.

rute digunakan sebagai middleware untuk memvalidasi parameter menggunakan ".param ()".

app.route () digunakan sebagai pintasan ke Router untuk menentukan beberapa permintaan pada suatu rute

ketika kita menggunakan app.route (), kita melampirkan aplikasi kita dengan router itu.

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')
})
Parth Raval
sumber
0

Dalam Versi 4 ekspres kita dapat dengan mudah menentukan rute dengan cara berikut:

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;

Di server.jskami mengimpor objek router dari route.jsfile dan menerapkannya dengan cara berikut di server.js:

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

Sekarang semua rute di route.jsmemiliki URL basis berikut:

http: // localhost: 3000 / rute

Mengapa pendekatan ini:

Keuntungan utama dari mengambil pendekatan ini adalah bahwa sekarang aplikasi kita lebih modular . Semua penangan rute untuk rute tertentu sekarang dapat dimasukkan ke dalam file yang berbeda yang membuat semuanya lebih mudah dirawat dan lebih mudah ditemukan.

Willem van der Veen
sumber