Devahoy Logo
PublishedAt

NodeJS

Fastify 101 - ทดลองเล่น Fastify เบื้องต้น

Fastify 101 - ทดลองเล่น Fastify เบื้องต้น

วันนี้ลองเล่น และลองอ่าน Overview ตัว Fastify เบื้องต้นดู ว่ามันเป็นยังไง หลังจากได้ยินมาซักพักแล้ว อยากรู้ว่าถ้าเปรียบเทียบกับ Express มันมีความเหมือน หรือต่างกันมากน้อยแค่ไหน และถ้าคนเขียน Express มาก่อน มาเขียน Fastify ต้องเปลี่ยน ต้องปรับอะไรแค่ไหนบ้าง

จาก Benchmark นี้ ตัว Fastify เคลมว่า ตัวเค้าเอง มี request/sec มากที่สุด (จากเว็บของ Fastify นะครับ ซึ่งจะมี bias มั้ย อันนี้ ตัดสินใจเอาเองครับ และก็ผล benchmark มันแค่ route เดียว ที่ Hello World ถ้าเว็บมัน complex มี feature มากขึ้น นอกจากเรื่อง framework แล้ว code quality ก็มีผลเช่นกัน)

  • Fastify 58,946 req/sec
  • Koa 46,240 req/sec
  • Restify 35,207 req/sec
  • Hapi 29,391 req/sec
  • Express 12,863 req/sec

ถ้าดูจาก benchmark คือ Express แย่สุด แต่ตัว Express ก็เหมือนเป็น framework คู่กับ Node.js ไปแล้ว และ web framework หลังๆ ก็เอารูปแบบการเขียน express หรือบางทีก็เป็น express เวอร์ชั่น lightweight built-in ไปเลยก็มี เช่น Next.js Middleware API, Nest.js เป็นต้น

Fastify

เริ่มแรกเลย เข้าเว็บ Fastify อ่าน Quick Start และลอง Getting Started จะเห็นว่า Hello World เขียนแทบไม่ต่างจาก Express.js เลย

server.js
1
// Require the framework and instantiate it
2
const fastify = require('fastify')({ logger: true })
3
4
// Declare a route
5
fastify.get('/', async (request, reply) => {
6
return { hello: 'world' }
7
})
8
9
// Run the server!
10
const start = async () => {
11
try {
12
await fastify.listen(3000)
13
} catch (err) {
14
fastify.log.error(err)
15
process.exit(1)
16
}
17
}
18
start()

นอกจากนี้ก็มี CLI ให้เราทำการ generate fastify ได้

Terminal window
npm install -g fastify-cli

สร้างโปรเจ็คด้วย fastify-cli

Terminal window
fastify generate hello-fastify

Routing

การกำหนด Route ใน Fastify ทำได้หลายแบบ แบบแรกคือ

1
fastify.route(options)

ซึ่ง options ก็มี properties เช่น

  • method - ตาม HTTP Method เลย คือ GET', PUT, POST, DELETE, PATCH, OPTIONS` เป็นต้น
  • url - path ของ Url ที่เราต้องการ match กับ route.
  • schema - เอาไว้ validate และ serialization
  • handler(request, resply) - function ที่เอาไว้ handle request

ตัวอย่าง ประมาณนี้

1
fastify.route({
2
method: 'GET',
3
url: '/',
4
handler: async (request, reply) => {
5
return { hello: 'world' }
6
}
7
})

หรือแบบใช้ function เป็นชื่อ HTTP Method คล้ายๆ Express ก็ทำได้ เช่น

1
fastify.get('/', (request, reply) => {})
2
3
fastify.post('/', (request, reply) => {})
4
5
fastify.get('/:id', (request, reply) => {})

Request

ตัว Request ก็รับค่าไม่ต่างจาก Express เช่น กำหนด route ไว้แบบนี้

1
fastify.post('/:id', async (request, reply) => {})

รับค่า จาก request payload / request body

1
request.body
2
3
// { data: 'your data' }

รับค่า Query string เช่น POST /:id?name=test

1
request.query
2
3
// { name: 'test' }

รับค่าจาก params เช่น POST /1000

1
request.params
2
3
// { id: 1000 }

รับค่าจาก request headers

1
request.headers
2
3
// { host: 'localhost:5555', 'user-agent': 'curl/7.79.1', accept: '*/*' }

Reply

Reply ก็เหมือน response หรือ res ของ Express เอาไว้กำหนดค่าต่างๆ การส่ง response ไป client เช่น

  • กำหนด cookie set-cookie
1
reply.header('set-cookie', 'something')
  • กำหนด statusCode
1
reply.statusCode = 400
  • กำหนด header / code / send
1
reply.code(200).header('Content-Type', 'application/json').send({ hello: 'world' })

Validation

ตัวอย่างการทำ validation ง่ายๆ เช่น เราจะส่ง POST / ด้วย id และ username ซึ่งถ้าส่ง property ไม่ครบ ก็ถูก reject (กำหนด type ให้ properties และกำหนด required เป็น property ที่ต้องการ)

1
fastify.route({
2
method: 'POST',
3
url: '/',
4
schema: {
5
body: {
6
type: 'object',
7
required: ['id', 'username'],
8
properties: {
9
id: { type: 'number' },
10
username: { type: 'string' }
11
}
12
}
13
},
14
handler: (request, reply) => {
15
return { success: true }
16
}
17
})

รายละเอียด Validation เพิ่มเติม Validation-And-Serialization

Plugins

ถ้าหากเราเปรียบเทียบว่า ใน JavaScript ทุกๆอย่างคือ Object ใน Fastify ก็มองทุกๆอย่าง เป็น Plugin เช่นกัน

syntax การ register plugin:

1
fastify.register(yourPlugin)

ตัวอย่าง Core Plugin ของ Fastify

TypeScript

ตัว Fastify ก็เขียนด้วย TypeScript ได้ปกติ เพียงแค่ใช้ ts และ types/node

1
npm i -D typescript @types/node

Initial typescript

1
npx tsc --init

สร้างไฟล์ main.ts ขึ้นมา

main.ts
1
import fastify from 'fastify'
2
3
const server = fastify()
4
5
server.get('/ping', async (request, reply) => {
6
return 'pong\n'
7
})
8
9
server.listen(8080, (err, address) => {
10
if (err) {
11
console.error(err)
12
process.exit(1)
13
}
14
console.log(`Server listening at ${address}`)
15
})

Compile typescript จะได้ไฟล์ main.js

1
tsc

ทดสอบรัน

1
node main.js

รองรับ Generic เช่น server.get() ตัว generic object มี properties ได้ เช่น QueryString, Headers`

1
interface IQuerystring {
2
username: string
3
password: string
4
}
5
6
interface IHeaders {
7
'h-Custom': string
8
}

ส่วน Route เราก็ define แบบ Generic โดยใช้ custom type ได้แบบนี้

1
server.get<{
2
Querystring: IQuerystring
3
Headers: IHeaders
4
}>('/auth', async (request, reply) => {
5
const { username, password } = request.query
6
const customerHeader = request.headers['h-Custom']
7
// do something with request data
8
9
return `logged in!`
10
})

อ่านเพิ่มเติม Fastify - TypeScript

นอกเหนือจากที่เขียนไว้ ก็ยังมี Concept และรายละเอียดอื่นๆ ให้ศึกษาเพิ่มเติม จาก Docs / Reference ครับ เช่น

Conclusion

สรุป ผมว่าคนที่เคยเขียน Express.js มาก่อน ถ้ามาจับ Fastify จริงๆ แล้ว แทบไม่ต่างกันเลย แนวคิดก็คล้ายกัน ตัว Syntax ก็เขียนคล้ายๆ กัน มีแค่เรื่อง Plugin ที่อาจจะต่างกันนิดหน่อย ส่วน syntax ตัวไหนไม่เข้าใจ ไม่ถนัด ก็อ่าน Docs / API มีรายละเอียดเกือบหมด

สุดท้ายแล้ว ผมคิดว่า ถ้าเรามี Fundamental ที่ดี เข้าใจพื้นฐาน เข้าใจการทำงานของ Web / API เราก็สามารถใช้ Framework หรือเครื่องมือไหนๆ ก็ได้ ไม่เข้าใจตรงไหน ก็อ่าน Docs เพิ่มเติมเอา

Happy Coding ❤️

Authors
avatar

Chai Phonbopit

เป็น Web Dev ในบริษัทแห่งหนึ่ง ทำงานมา 10 ปีกว่าๆ ด้วยภาษาและเทคโนโลยี เช่น JavaScript, Node.js, React, Vue และปัจจุบันกำลังสนใจในเรื่องของ Blockchain และ Crypto กำลังหัดเรียนภาษา Rust

Related Posts