เนื้อหาต่อไปนี้ จะเป็นการทำความรู้จักกับ Routing ใน Express
รวมทั้งรูปแบบ และการใช้งานเบื้องต้น เพื่อเป็นแนวทางสำหรับ
เนื้อหาต่อๆ ไป เกี่ยวกับ Express
ต่อจากบทความ Express web framework เบื้องต้น http://niik.in/906
เรามาดูไฟล์ app.js ที่เราได้ทดสอบรันผ่าน บราวเซอร์มาแล้ว
const express = require('express') // ใช้งาน module express const app = express() // สร้างตัวแปร app เป็น instance ของ express const port = 3000 // port // ส่งกลับข้อความ "hello world" เมื่อมี GET request มายังหน้า homepage app.get('/', function (req, res) { res.send('hello world ') }) app.listen(port, function() { console.log(`Example app listening on port ${port}!`) })
Routing คืออะไร
Routing คือการกำหนด URL หรือ Path ที่ใช้ในการเรียกข้อมูลผ่าน HTTP request เช่น
GET POST PUT หรือ DELETE แล้วให้ทำการ response หรือส่งกลับข้อมูลหรือการทำงานใดๆ
ให้สอดคล้องกับ URL ใดๆ ที่ระบุเข้ามา
การ response หรือส่งกลับข้อมูลด้วยการทำคำสั่งใดๆ นั้น เราสามารถกำหนดได้ว่า จะให้ทำคำสั่ง
เดียวหรือหลายคำสั่ง เมื่อผู้ใช้ request เข้ามายัง path และเข้าเงื่อนไขการทำงาน ยกตัวอย่าง
จากโค้ดด้านบน
app.get('/',function(){});
รูปแบบการกำหนด Route
app.METHOD(PATH, HANDLER)
โดย
app คือ instance ของ express (เข้าใจง่ายๆ "ฉัน (app)" คือตัวแทนของ express )
METHOD คือ HTTP request method ใช้เป็นตัวเล็ก หมายถึง ทำการเรียกข้อมูลผ่าน HTTP ด้วยวิธี
* get | post | put | delete
PATH คือ URL หรือ ส่วนของโดนเมนนับตั้งแต่ "/" ตัวที่ 3 เป็นต้นไป เช่น
*http://niik.in/forum จะได้ PATH คือ "/fourn" ถ้าเป็น Root PATH ก็คือ "/"
HANDLER คือฟังก์ชั่นที่กำหนดให้ทำงาน เมื่อ PATH ตรงกับค่าที่กำหนด
โค้ดด้านล่าง แสดงถึงการกำหนด Route อย่างง่าย โดย response หรือส่งกลับคำว่า "hello world"
ไปแสดงที่หน้าแรก หรือ homepage
// ส่งกลับข้อความ "hello world" เมื่อมี GET request มายังหน้า homepage app.get('/', function (req, res) { res.send('hello world ') })
Express ไม่เพียงแค่รองรับ GET POST PUT หรือ DELETE method แต่ยังสามารถรองรับ method ต่างๆ
ตามลิสรายการด้านล่าง โดยวิธีการทำงาน ก็จะสัมพันธ์กับชื่อที่ใช้เรียก Method นั้นๆ แต่อย่างไรก็ตาม
การใช้งานส่วนใหญ่เกือบทั้งหมด ก็จะเป็นการใช้งานใน 4 method ข้างต้น
Route methods
Route method นั้นถูกแปลงมาจาก HTTP method แล้วนำมาผูกเข้ากับ instance ของ express class
ตัวอย่างด้านล่าง คือโค้ดบางส่วนของการกำหนด route แบบ GET และ POST method ให้กับ Root ของ app
// GET method route app.get('/', function (req, res) { res.send('GET request to the homepage') }) // POST method route app.post('/', function (req, res) { res.send('POST request to the homepage') })
โดยเมื่อมี HTTP request ขึ้น ก็จะทำให้เกิด request object และ response object โดย object ทั้งสอง
เราสามารถนำเข้าไปใช้งานในฟังก์ชั่น เพื่อกำหนด หรือทำงานต่างๆ ต่อไปได้ ในโค้ดตัวอย่างใช้ตัวแปรอักษร
3 ตัวแบบย่อคือ req = request และ res = response
ตัวอย่าง ค่า req บางค่าก็เช่น req.url หรือ req.method เป็นต้น
ตัวอย่าง ค่า res บางค่าก็เช่น res.rawHeaders หรือ res.statusCode เป็นต้น
นอกจาก Method ต่างๆ ข้างต้นแล้ว ยังมี method พิเศษ ในการกำหนด Routing คือ app.all() ซึ่งใช้สำหรับ
กำหนดให้ทำงานใน middleware ฟังก์ชั่น หรือ ฟังก์ชั่นที่ใช้สำหรับจัดการกับ HTTP request ทุก method
ใดๆ ก็ตามที่เกิดขึ้น เข้าใจอย่างง่ายก็คือ สมมติเกิด GET request มาที่ "/" เราสามารถใช้ฟังก์ชั่น middleware
มาดักจับตัว request แล้วปรับปรุงเปลี่ยนแปลงค่าต่างๆ ก่อนที่ค่านั้น จะผ่านเข้ามาในฟังก์ชั่น HANDLER ของ
method นั้น ยกตัวอย่าง เราเพิ่มโค้ด การใช้งาน app.all() เข้าไปก่อนการ เรียกใช้ GET method ดังนี้
// ดักจับทุกๆ method app.all('/', function (req, res, next) { console.log('Accessing the secret section ...') res.myobj = 1; // สมมติเราเพิ่ม req property ที่ชื่อ myobj เท่ากับ 1 next() // ให้ไปทำงานต่อ handler ฟังก์ชั่นในลำดับถัดไป }) // ส่งกลับข้อความ "hello world" เมื่อมี GET request มายังหน้า homepage app.get('/', function (req, res) { console.log(res.myobj) // ทดสอบแสดงค่า ที่เราปรับแต่ง req res.send('hello world ') })
ดูผลลัพธ์
จะเห็นว่าข้อความ "Accessing the secret section ..." ซึ่งอยู่ใน middleware function
ที่เรากำหนดเอง แสดงก่อน จากนั้น เราก็ทำการเพิ่ม property เข้าไปใน req object ชื่อ
myobj กำหนดค่า เท่า 1 เสร็จแล้วก็ใช้ฟังก์ชั่น next() เพื่อไปทำคำสั่ง ลำดับถัดไป
ซึ่งก็คือฟังก์ชั่นที่ทำงานเมื่อมี GET Request มาที่ "/" ก็จะแสดง req.myobj ค่าที่เราได้ปรับแต่ง
เพิ่มเติม ถูกส่งเข้ามา และแสดงผลออกทาง console ตามรูป นั่นก็หมายความว่า การดักจับการทำงาน
หรือการแทรกการทำงานด้วย middleware ฟังก์ชั่นข้างต้น สามารถทำงานได้
นอกจาก middleware ที่เรากำหนดแล้ว ยังมี middleware ฟังก์ชั่นอื่นๆ ที่เราสามารถเรียกใช้งานได้
ซึ่งจะได้รู้จักในลำดับต่อๆ ไป
Route paths
เราได้รู้จักเกี่ยวกับ route path บางส่วนไปแล้ว ซึ่งส่วนของ Path เป็นส่วนที่ใช้งานร่วมกับ
request method โดยสามารถกำหนดเป็น
stinrg เช่น "/" , "/about" , "/random.text" เป็นต้น
string pattern เช่น "/ab?cd" , "/ab+cd" , "'/ab*cd'" เป็นต้น
regular expression เช่น /a/ , /.*fly$/ เป็นต้น
ตัวอักขระ ?, +, * และ () เป็นส่วนหนึ่งของรูปแบบ regular expression
สัญลักษณ์ (-) hyphen และ dot (.) เป็นส่วนหนึ่งของ string
สัญลักษณ์ ($) dollar sign สามารถกำหนดใน path โดยต้องไว้ในในเครื่องหมาย ([ และ ])
ยกตัวอย่าง เช่น เรียกไปที่ path "/data/$book" ต้องกำหนดเป็น "/data/([\$])book"
ตัวอย่างการกำหนด route path ในรูปแบบต่าง
รูปแบบ String
app.get('/', function (req, res) {}) // Root route: / app.get('/about', function (req, res) {}) // route: /about app.get('/random.text', function (req, res) {}) // route: /random.text
รูปแบบ String Pattern
app.get('/ab?cd', function (req, res) {}) // route: /acd และ abcd // เครื่องหมาย ? วางอยู่หลังตัวอักขระใดๆ หมายถึง ตัวนั้นๆจะมี หรือไม่มีก็ได้ app.get('/ab+cd', function (req, res) {}) // route: /abcd และ /abbcd และ /abbbcd...ไปเรื่อยๆ // เครื่องหมาย + วางอยู่หลังตัวอักขระใดๆ หมายถึง ต้องมีตัวนั้นๆ อย่างน้อย 1 หรือก็คือ มี b กี่ตัวก็ได้ app.get('/ab*cd', function (req, res) {}) // route: /abcd, /abxcd, /abRANDOMcd ...ไปเรื่อยๆ // เครื่องหมาย * วางอยู่ตำแหน่งใดๆ เหมือนถึงไม่มี หรือมีตัวอักษระใดๆ ก็ได้ app.get('/ab(cd)?e', function (req, res) {}) // route: /abe และ /abcde // เครื่องหมายวงเล็บใช้จัดกลุ่มของข้อมูล และใช้ร่วมกับเครื่องหมายอื่น ดังนั้นจึงหมายถึง มี cd หรือไม่ก็ได้
รูปแบบ Regular Expression
สามารถอ่านเพิ่มเติมได้ที่ (Regular Expression in PHP)
app.get(/a/, function (req, res) {}) // route: ทุกๆ path ที่มี "a" อยุ่ในนั้น เช่น // route: /about , /contact app.get(/.*fly$/, function (req, res) {}) // route: ทุกๆ path ที่ลงท้ายด้วย fly เช่น // route: /butterfly , /dragonfly
Route parameters
Route parameter หรือเรียกอีกอย่างหนึ่งว่า URL segments เป็นส่วนที่ใช้สำหรับเก็บค่าไว้ในตำแหน่งต่างๆ
ของ URL โดยค่าเหล่านี้ จะถูกเรียกใช้งานผ่าน req.params object กล่าวคือ โดยชื่อของ parameter
จะกำหนดเป็นชื่อ key ในรูปแบบ :[key ชื่อ parameter] เรียงตามลำดับ
Route path: /users/:userId/books/:bookId Request URL: http://localhost:3000/users/34/books/8989 req.params: { "userId": "34", "bookId": "8989" }
สังเกต ชื่อ parameter จาก URL ข้างต้น จะมีด้วยกัน 2 key คือ :userId และ :bookId
ในการกำหนด route path ที่มี route parameter ตามรูปแบบข้างต้น สามารถทได้ดังนี้
app.get('/users/:userId/books/:bookId', function (req, res) { res.send(req.params) })
ชื่อ parameter ต้องกำหนดเป็น ข้อความที่เป็นตัวเลขและตัวอักษรภาษาอังกฤษตามรูปแบบ
([A-Za-z0-9_]) ประกอบด้วยตัวพิมพ์เล็กหรือตัวพิมพ์ใหญ่หรือตัวเลขหรือสัญลักษณ์ _ (underscore)
สำหรับ hyphen (-) และ dot (.) สามารถใช้งานร่วมกับ route parameter เพื่อวัตถุประสงค์พิเศษ
บางอย่างได้ เช่น เชื่อม parameter 2 ตัวด้วย (-) หรือ (.) เข้าด้วยกัน
Route path: /flights/:from-:to Request URL: http://localhost:3000/flights/LAX-SFO req.params: { "from": "LAX", "to": "SFO" }
Route path: /plantae/:genus.:species Request URL: http://localhost:3000/plantae/Prunus.persica req.params: { "genus": "Prunus", "species": "persica" }
นอกจากนั้น เรายังสามารถใช้วงเล็บ () ต่อท้าย parameter ที่เราต้องการกำหนดรูปแบบของข้อมูลที่
จะใช้งานได้ เช่่น (\d+) คือ ต้องมีตัวเลข ตัวอย่างการกำหนดเพิ่มเติม
\d -- ตัวเลขทุกตัว 0 - 9 \D -- ตัวอักขระทุกตัว ยกเว้น เลข 0 - 9 \s -- ช่องว่างทุกตัว \S -- ตัวอักขระทุกตัว ยกเว้นช่องว่าง \w -- ตัวอักษร ตัวเลข ทุกตัว ยกเว้นตัวอักขระพิเศษ . \ + * ? [ ^ ] % $ ( ) { } = ! < > | : - \W -- ตัวขระพิเศษทุกตัว และช่องว่าง ยกเว้น ตัวอักษร และตัวเลข
สามารถดูได้ที่ http://niik.in/396
ซึ่งกรณีมีการใช้งาน \ ใน regular expression ให้เราเพิ่มเป็น \\ เพราะถ้ามีตัวเดียว
จะถูกตีความว่าเป็น string ตัวหนึ่งเท่านั้น ทำให้ไมีมีการแปลงความหมายของค่ากำหนด
กล่าวคือ ถ้ากำหนดเป็น \d จะมอง \ และ d เป็น string ปกติทั่วไป แต่ถ้า กำหนดเป็น \\d
จะตีความหมายและแปลงเป็นเงื่อนไขว่า เป็นตัวเลขทุกตัว 0-9 แบบนี้เป็นต้น
app.get('/users/:userId(\\d+)', function (req, res) { res.send(req.params) })
Route handlers
Route handler หรือก็คือฟังก์ชั่นส่วนที่ทำงานเมื่อเข้าเงื่อนไข หรือ url ที่ผู้ใช้งานเรียกเข้ามา
ตรงกับรูปแบบที่เรากำหนด อย่างที่ได้เข้าใจไปบ้างแล้วในตอนต้นกริ่นนำว่า เราสามารถกำหนดให้ ทำ
ฟังก์ชั่นได้มากกว่า 1 ฟังก์ชั่น โดยใช้ middleware function เข้ามาช่วย โดยมีคำสั่ง next()
เพื่อส่งไปทำงานฟังก์ชั่นที่เหลือ
เราสามารถกำหนด route handler ในรูปแบบของฟังก์ชั่น ,อาเรย์ของฟังก์ชั่น หรือทั้งสองอย่างรวมกันก็ได้
ตัวอย่างด้านล่างเป็นรูปแบบฟังก์ชั่นเดี่ยว ที่เราเห็นตัวอย่างมาบ่อยแล้ว
รูปแบบฟังก์ชั่นเดียว
app.get('/example/a', function (req, res) { res.send('Hello from A!') })
รูปแบบหลายฟังก์ชั่น
app.get('/example/a', function (req, res, next) { req.myobj = 'Hello from A!' next() },function(req, res){ req.myobj += ' Again!!!' res.send(req.myobj) })
ฟังก์ชั่นแรก เรากำหนด req.myobj เท่ากับ 'Hello from A!' จากนั้นส่งต่อไปฟังก์ชั่นที่ สอง
โดยเพิ่มคำว่า ' Again!!' เข้าไป เสร็จแล้ว ส่งออกไปแสดงหน้าบราวเซอร์ จะได้ผลลัพธ์ดังรูป
รูปแบบ array ของฟังก์ชั่น
var func_a = function(req, res, next) { req.myobj = 'A' next(); } var func_b = function(req, res, next) { req.myobj += ' B' next(); } var func_c = function(req, res) { req.myobj += ' C' res.send(req.myobj); } app.get('/example/a', [func_a,func_b,func_c])
รูปแบบผสมหลายแบบ
var func_a = function(req, res, next) { req.myobj = 'A' next(); } var func_b = function(req, res, next) { req.myobj += ' B' next(); } app.get('/example/a', [func_a,func_b],function (req, res, next){ req.myobj += ' C' next(); },function(req, res){ req.myobj += ' D' res.send(req.myobj); });
Response methods
ใน response นั้น (res - response object) จะมี method ที่ทำหน้าที่ส่งกลับข้อมูลมายังผู้ใช้งาน และสิ้นสุดการทำงาน
ของกระบวนการ request response ที่เกิดขึ้น ซึ่งถ้าไม่มีการใช้งาน method ในส่วนนี้ การ request จากฝั่งผู้ใช้ อาจจะ
มีอาการค้างหรือหยุดการทำงานไป
รายการ response method ที่ใช้บ่อย ประกอบไปด้วย
res.download()
ทำการดาวน์โหลดไฟล์ที่ต้องการ
res.download('/report-12345.pdf'); res.download('/report-12345.pdf', 'report.pdf'); res.download('/report-12345.pdf', 'report.pdf', function(err){ if (err) { // อาจจะส่งข้อความแจ้งว่า ดาวน์โหลดไม่สำเร็จ หรืออื่นๆ โดยใช้ res.send() } else { // ทำคำสั่งอื่นๆ เช่น นับจำนวนการดาวน์โหลด } });
// ตัวอย่างดาวน์โหลดโฟล์ app.js2 ซึ่งไม่มีไฟล์ดังกล่าง เป็นชื่อ mysavefile.txt app.get('/download',function(req, res){ res.download('app.js2','mysavefile.txt',function(err){ if (err) { // console.log(res.headersSent) console.log(err) console.log("Can't downlaod") res.send("Can't download file!") } else { console.log("file downloaed") } }) })
res.end()
จบการทำงาน โดยไม่ส่งค่าใดๆ กลับ
res.end(); res.status(404).end();
res.json()
ส่งกลับข้อมูลในรูปแบบ JSON string
res.json(null); res.json({ user: 'tobi' }); res.status(500).json({ error: 'message' });
res.jsonp()
ส่งกลับข้อมูลในรูปแบบ JSON string รองรับ JSONP
res.jsonp(null); // => callback(null) res.jsonp({ user: 'tobi' }); // => callback({ "user": "tobi" }) res.status(500).jsonp({ error: 'message' }); // => callback({ "error": "message" }) // ?callback=foo res.jsonp({ user: 'tobi' }); // => foo({ "user": "tobi" }) // กรณีกำหนด callback name เป็นชื่ออื่น app.set('jsonp callback name', 'cb'); // ?cb=foo res.status(500).jsonp({ error: 'message' }); // => foo({ "error": "message" })
res.redirect()
ลิ้งค์หรือเปลี่ยน path ไปยัง url ที่กำหนด เช่น
res.redirect('/foo/bar'); res.redirect('http://example.com'); res.redirect(301, 'http://example.com'); res.redirect('../login'); res.redirect('..'); // การย้อนกลับมา 1 path res.redirect('back'); // การย้อนกลับไป path ก่อนหน้า
res.render()
สร้าง HTML string จาก view template แล้วส่งออกมาแสดง เราจะได้ศึกษาเพิ่มเติม เกี่ยวกับ view template
res.send()
ส่งข้อมูลกลับมาแสดง โดยสามารถเป็น Buffer Object , String ข้อความ , Object และ Array เช่น
res.send(new Buffer('whoop')); res.send({ some: 'json' }); res.send('<p>some html</p>'); res.send([1,2,3]); res.status(404).send('Sorry, we cannot find that!'); res.status(500).send({ error: 'something blew up' });
res.sendFile()
ส่งไฟล์ หรือนำข้อมูลไฟล์มาแสดง Send a file as an octet stream
app.get('/about',function(req, res){ // ตัวอย่งแสดงไฟล์ about.html ที่อยู่ใน root // ซึ่งเวลาใช้งานจริง เราจะใช้ path module มาข่วย จะไม่กำหนดลักษณะนี้ // res.sendFile(path.join(__dirname+'/about.html')); // กรณีใช้ path module res.sendFile("C:\\projects\\expressjs\\about.html") })
res.sendStatus()
กำหนด status code และ ส่งข้อความแจ้ง เช่น
res.sendStatus(200); // มีค่าเท่ากับใช้คำสั่ง res.status(200).send('OK') res.sendStatus(403); // มีค่าเท่ากับใช้คำสั่ง res.status(403).send('Forbidden') res.sendStatus(404); // มีค่าเท่ากับใช้คำสั่ง res.status(404).send('Not Found') res.sendStatus(500); // มีค่าเท่ากับใช้คำสั่ง res.status(500).send('Internal Server Error')
ข้างต้น เป็น response method ที่เราจะได้เจอบ่อยๆ ในการใช้งาน express ยังมี method อื่นๆ อีก
รวมถึง method ที่กล่าวมายังมีรายละเอียด ที่เราต้องศึกษาเพิ่มเติมในลำดับต่อๆ ไป
app.route()
เราสามารถเชื่อมการทำงานให้กับ route เป็นฟังก์ชั่นต่อๆ กัน หรือที่เรียกว่า chain โดยการใช้งาน app.route()
ซึ่งจะช่วยลดขั้นตอนที่ซับซ้อนและป้องกันความผิดพลาดในการพิมพ์ เพราะบางครั้ง เรามีการกำหนด route path
ซ้ำๆ กันให้กับ method ต่างๆ ดังนั้น การกำหนด route path ที่เดียว แล้วกำหนด method แยกย่อยลงไป จะทำให้
ลดขั้นตอนการเขียนลงได้ ตามตัวอย่างด้านล่าง
app.route('/book') .get(function (req, res) { res.send('Get a random book') }) .post(function (req, res) { res.send('Add a book') }) .put(function (req, res) { res.send('Update the book') })
express.Router
ในการพัฒนา web app ที่มีความซับซ้อนหรือมีโครงสร้างการทำงานจำนวนมาก การกำหนด route path ไว้ในไฟล์ app.js
คงไม่ใช่วิธีที่ถูกต้องหรือเหมาะสม การสร้างไฟล์แยกเป็นอีก module หรือก็คือการสร้าง mini-app แยกย่อย แล้วค่อยนำมา
เรียกใช้งานในไฟล์หลัก จึงเป็นวิธีที่เหมาะสมที่ถูกนำมาใช้งาน
โดยเราสามารถใช้ express.Router class เพื่อสร้าง module หรือสร้างไฟล์ module ใหม่ ที่สามารถเชื่อมกับการจัดการ
ของฟังก์ชั่นใน route ตัว Router ที่เป็น instance ของ expressRouter ก็คือ middleware ตัวหนึ่งที่เราสามารถเรียกใช้งาน
ในไฟล์หลัก
ทดสอบ เพื่อทำควาเข้าไจ ตามลำดับดังนี้
ให้เราสร้างไฟล์ birds.js ไว้ใน root โฟลเดอร์ ที่เดียวกับ app.js แล้วกำหนดโค้ดตามตัวอย่างด้านล่าง
var express = require('express') // เรียกใช้งาน express mudule var router = express.Router() // กำหนด router instance ให้กับ express.Router class // เราใช้คำสั่ง use() เพื่อเรียกใช้งาน middleware function // middleware ที่กำงานใน router instance ก่อนเข้าไปทำงานใน route function router.use(function timeLog (req, res, next) { console.log('Time: ', Date.now()) next() }) // กำหนด route หลัก หรือ root route router.get('/', function (req, res) { res.send('Birds home page') }) // กำหนด route เพิ่มเติม router.get('/about', function (req, res) { res.send('About birds') }) module.exports = router // ส่ง router ที่เราสร้าง ออกไปใช้งานภายนอกไฟล์
จากนั้นมาที่ไฟล์ app.js เราจะทำการโหลด router module จากไฟล์ birds.js ที่เราสร้างมาใช้งาน โดยทำได้ดังนี้
const express = require('express') // ใช้งาน module express const app = express() // สร้างตัวแปร app เป็น instance ของ express const port = 3000 // port const birds = require('./birds') // ใช้งาน router module // เรีรยกใช้งานในรูปแบบ middlewar โดยใช้ use app.use('/birds', birds) // ส่งกลับข้อความ "hello world" เมื่อมี GET request มายังหน้า homepage app.get('/', function (req, res) { res.send('hello world ') }) app.listen(port, function() { console.log(`Example app listening on port ${port}!`) })
จะเห็นว่า เราสามารถกำหนด กี่ module เข้ามาก็ได้ โดยใช้ use()
ถ้าเราสังเกตดีๆ จะพบว่า ในไฟล์ app.js มีการกำหนด route path ของหน้าแรก app ไว้แล้ว คือให้แสดง hello world
แล้วทำไมในไฟล์ birds จึงมีการกำหนด root route path เหมือนกัน แล้ว จะมีการเรียกไปที่ path ไหนเมื่อเข้าหน้าแรก
คำตอบคือ ให้สังเกตจากการกำหนด path ของ router module ที่เราเรีรยกใช้ เรากำหนดเป็น
app.use('/birds', birds)
นั่นหมายความว่า router.get('/') ในไฟล์ birds.js จึงหมายถึง path: /birds
และ router.get('/about') ในไฟล์ birds.js จึงหมายถึง path: /birds/about
แล้วถ้าเราเปลี่ยนหน้า app.js เป็น
app.use('/', birds)
ลักษณะแบบนี้ คือเป็นการเปลี่ยน route path หลักไปที่ birds module ดังนั้น เมื่อเข้าหน้าแรก
จึงเข้าไปทำงานในไฟล์ birds.js แทน และไม่แสดงคำว่า hello worldl
ดูตัวอย่างผลลัพธ์ประกอบ
สมมติเราเปลี่ยนเป็น app.use('/', birds) ก็จะได้หน้าแรกเป็นดังนี้
ในเนื้อหาตอนนี้ เราได้เข้าใจส่วนต่างๆ ของ Routing ไปพอสมควรแล้ว หวังว่าจะเป็นแนวทาง
สำหรับทำความเข้าใจในส่วนอื่นๆ เพิ่มเติมต่อไป