สวัสดีครับ มาต่อกันที่ตอนที่ 8 กันนะครับ หลังจากหายไปนานเป็นอาทิตย์เลย พอดีช่วงนี้งานยุ่งมากๆ ตอนก่อนหน้านี้เราได้รู้จักกับ MongoDB กันไปแล้ว วันนี้เราจะมาเขียน MongoDB ร่วมกับ Node.js กันนะครับ

แต่บางคนอาจจะสงสัยข้ามตอน 7 ไปรึเปล่า จริงๆผมกะจะเขียนตอน 7 แต่รู้สึกว่าเนื้อหาเป็นสิ่งที่ผมเคยเขียนไปแล้วนี่นา เลยคิดว่า เอาที่เขียนอันเก่า มาใส่ในซีรีย์น่าจะง่ายกว่า ไม่อยากเขียนซ้ำครับ

เนื้อหาบทเรียน


เพื่อนๆอาจจะสงสัย ว่าทำไมทุกครั้งที่เราสร้าง Web ขึ้นมาด้วย Express เนี่ย เราต้องมาสร้างโฟลเดอร์ สร้างไฟล์ server สร้าง package.json กำหนด view template ต่างๆ ด้วย ตัว Express มีทำให้เรามั้ย?

คำตอบคือมีครับ ตัว Express จะมีตัว Express Generator แยกออกมาต่างหากครับ

Express Generator

ตัว Express Generrator เป็นตัวช่วยให้เราสามารถสร้างโปรเจ็ค Express โดยใช้ Template ที่ Express มีให้ครับ

เราสามารถสั่ง Generator ผ่านตัว npx ได้เลยครับ

npx เป็นการใช้ Node package จาก npmjs (npm registry) โดยที่เราไม่ต้องติดตั้งลงเครื่องครับ ปกติเราต้องลงบนโฟเดอร์ หรือ global ด้วย npm install express-generator -g เป็นต้น

เข้า Terminal ไปที่โฟลเดอร์ที่เราต้องการ หรือสร้างใหม่ก็ได้ จากนั้น

npx express-generator --view=pug my-app

สิ่งที่ผมใส่ --view=pug คือเราให้ Template Engine เป็น Pug ครับ ถ้าไม่ใส่ default จะเป็น Jade ซึ่งมัน deprecated ไปแล้วครับ หากมีอัพเดทในอนาคตมันอาจจะใช้ไม่ได้

จะเห็นว่าตัว Generator มันสร้างไฟล์และโฟลเดอร์ให้เราพร้อมเลย

   create : my-app/
   create : my-app/public/
   create : my-app/public/javascripts/
   create : my-app/public/images/
   create : my-app/public/stylesheets/
   create : my-app/public/stylesheets/style.css
   create : my-app/routes/
   create : my-app/routes/index.js
   create : my-app/routes/users.js
   create : my-app/views/
   create : my-app/views/error.pug
   create : my-app/views/index.pug
   create : my-app/views/layout.pug
   create : my-app/app.js
   create : my-app/package.json
   create : my-app/bin/
   create : my-app/bin/www

   change directory:
     $ cd my-app

   install dependencies:
     $ npm install

   run the app:
     $ DEBUG=my-app:* npm start

จากนั้นลองสั่ง start server ดูครับ (อย่าลืม install dependencies ด้วยนะ)

cd my-app
npm install

Start โลด

npm start

จะได้หน้าเว็บ Express พร้อมใช้งานให้เราเลย http://localhost:3000/

Express generator hello ;

ทีนี้มาดูว่าเราได้ Folder อะไรมาบ้าง

  • app.js - เป็นไฟล์หลักของเรา นั่นเอง และตัว Generator ไม่ได้สั่ง listen และ start server ด้วยไฟล์นี้ ไฟล์นี้เพียงแค่รวบทุกไฟล์ไว้ด้วยกัน
  • bin/www - เป็นเหมือนตัว Server ของเราครับ import app.js มา และเป็นตัว listener รวมถึงดัก Error ของ server
  • views - เป็น Folder ของ view template ที่ถูก generate มาให้แล้ว 3 ไฟล์
  • routes - โฟลเดอร์ที่แยก หน้าแต่ละหน้าของเว็บ โดยมี 2 หน้าเช่น index.js กับ users.js ทำให้เราสามารถเขียนแยก Modules ได้นั่นเอง แล้วค่อยไปรวมกันที่ไฟล์ app.js โดยการ import จะได้ไม่ต้องเขียนทุกๆอย่างในไฟล์เดียวครับ
  • public - เป็นโฟลเดอร์ของพวกไฟล์ assets ต่างๆ ทั้งรูป css และ javascript (ถ้ามี)

จะเห็นว่า เราใช้ Express Generator นั้นง่ายมากๆ และเรายังสามารถนั่งดู นั่งไล่โค๊ดที่มัน Generate มาให้เพิ่มเติมได้อีกครับ

ลองไปใช้กันดู และลองปรับเพิ่ม Module เพิ่ม Feature กันดูนะครับ ใช้ไม่ยากเลย

Express Middleware

มากันที่เรื่องของ Middleware ใน Express จริงๆแล้วเรื่อง Middleware เป็นเรื่องสำคัญ ที่จะต้องพูดถึงในโลกของ Express เลยครับ เพราะหลักๆแล้ว ตัว Middleware นี่แหละที่เป็นตัวขับเคลื่อน Express

Middleware function มันคือ function ที่สามารถเข้าถึง Object request และ response ได้ หรือที่เราคุ้นในชื่อย่อ req และ res นั่นแหละ และก็ function next ที่เอาไว้ call middleware ถัดไป

หรือจะมองง่ายๆ ก็คือมันเป็นตัวขั้นกลาง ระหว่าง request ของ client และ response จาก server ก็ได้ครับ

ซึ่ง Middleware มันทำอะไรได้บ้าง?

  • สามารถแก้ไข request และ response ได้
  • สามารถจบการทำงานของ request/response ได้ (ปกติ Client ส่ง request มาให้ Server กำลังประมวลผล แต่ตัว middleware สามารถจบการทำงาน​โดยการส่ง response กลับไปว่า success หรือ error ประมาณนี้)
  • call middleware ถัดไป ใน stack (ส่วนนี้อาจจะยังงงๆ เดี๋ยวจะอธิบายเพิ่มเติม)

ตัวอย่าง Middleware ไว้ console.log เวลามี request เข้ามา เช่น

const showLog = (req, res, next) => {
  console.log('Request >> ', req)
  next()
}

ฟังชั่นนี้เป็น middleware function ของ Express แล้วครับ เนื่องจากตรงตามเงื่อนไขคือ req, res และ callback function ชื่อ next ตัวที่ 3 (จริงๆเราใช้ชื่ออะไรก็ได้นะ แต่ใช้ next เพื่อให้เข้าใจง่าย เพราะเวลาเรียก next() มันก็คือการไป next middleware ถัดไป)

ซึ่งเรานำ showLog ที่เป็น Middlware มาใช้ปกติ เราก็ต้องใช้ app.use() เพื่อ register middleware ก่อน

const express = require('express');
const app = express();

const showLog = (req, res, next) => {
  console.log('Request >> ', req);
  next();
});

app.use(showLog);

app.get('/', (req, res) => {
  res.send('Hello World!');
})

app.listen(3000);

ทีนี้ ทุกครั้งที่มี request มา มันจะทำการ print ค่า req ก่อน จากนั้นถึง callback next() เพื่อมาอีก middleware นั่นคือ app.get('/') จากนั้น app.get('/') ก็ response Hello World! กลับไปนั่นเอง เป็นการจบ cycle ของ request / response ครับ

ข้อควรระวังในการสร้าง Middleware คือ หากเราไม่ได้ response ค่ากลับ เราต้องเรียก next() เพื่อส่งต่อไปอีก middleware ไม่งั้น server จะค้างได้ เพราะมันไม่มี response กลับมานั่นเอง

หรืออาจจะยุบ middleware ไปใน app.use() เลยก็ได้แบบนี้

app.use((req, res, next) => {
  console.log('Request >> ', req)
  next()
})

หรือในระดับ Router ก็ได้เช่นแบบนี้ ก็จะมีผลแค่เฉพาะ path /users/:id ครับ

app.use('/users/:id', (req, res, next) => {
  console.log('Request >> ', req.params)
  next()
})

เมื่อมาถึงตรงนี้เพื่อนๆ ก็อาจจะร้องอ๋อละว่า เราก็ได้ใช้ Middleware กันมาก่อนแล้วนี้น่า เช่น body-parser หรือ app.use() ต่างๆ

หวังว่าเรื่อง Middleware จะทำให้เพื่อนๆได้เห็นภาพการทำงานของมันนะครับ เพราะในอนาคต เราจะได้ใช้ Middleware กันมากขึ้น รวมถึงตอนหน้าจะเป็นการทำ Login ครับ ซึ่งจะมี Passport.js และมี Middleware ด้วยครับ

References

เอกสารเพิ่มเติมสำหรับ Express Generator และ Middleware จริงๆแล้ว อ่านได้จาก Official Doc ได้เลยครับ


หากใครติดปัญหา หรือไม่เข้าใจตรงไหน สามารถสอบถามได้ครับ หรือหากใครเจอข้อผิดพลาด สามารถแนะนำได้เช่นกันครับ

ส่วน Source Code (อยู่ part8) สามารถเข้าไปดาวน์โหลด หรือ clone ผ่าน Github ได้เลย หากใครไม่รู้จัก Git สามารถอ่านบทความนี้เพิ่มได้ครับ Git คืออะไร ? + พร้อมสอนใช้งาน Git และ Github

Source Code

ขอบคุณครับ

❤️ Happy Coding