Cloudflare Workers คืออะไร
Cloudflare Workers คือ Serverless Platform ที่รันโค้ด JavaScript ที่ Edge Node ของ Cloudflare ทั่วโลก (มากกว่า 300 เมือง) แทนที่จะรันที่ Server กลางเพียงแห่งเดียว ทำให้ผู้ใช้ได้รับการตอบสนองจาก Node ที่อยู่ใกล้ที่สุด Latency จึงต่ำกว่าการใช้ Server ดั้งเดิมมาก
สิ่งที่ทำให้ Cloudflare Workers โดดเด่น:
- V8 Isolates — แต่ละ Worker รันใน Isolate แยกกันของ V8 Engine (เดียวกับ Chrome) ไม่ใช่ Container หรือ VM ทำให้ Cold Start เร็วมาก (ต่ำกว่า 1ms) เทียบกับ AWS Lambda ที่อาจใช้เวลาหลายร้อย ms
- Edge Runtime — โค้ดรันที่ Edge Node ใกล้ผู้ใช้ ลด Latency จากการส่งข้อมูลข้ามทวีป
-
Web Standards API — ใช้ API มาตรฐานเดียวกับ Browser เช่น
Request,Response,fetch(),Headersทำให้โค้ดคุ้นเคยและย้ายแพลตฟอร์มได้ง่าย - Free Tier ใจดี — 100,000 requests/วัน ฟรี เหมาะสำหรับโปรเจกต์ขนาดเล็กและนักศึกษา
สถาปัตยกรรม Cloudflare Workers:
ผู้ใช้ในไทย ผู้ใช้ในญี่ปุ่น ผู้ใช้ในยุโรป
│ │ │
▼ ▼ ▼
CF Edge: Bangkok CF Edge: Tokyo CF Edge: Frankfurt
│ │ │
└─────────────────────┴────────────────────┘
│
Cloudflare Network
(Worker รันที่ Edge ใกล้ผู้ใช้)
เปรียบเทียบ: Traditional Server
ผู้ใช้ทุกคน ──────────────────────► Server กลาง (เช่น สิงคโปร์)
(ทุกคนรอเท่ากัน ไม่ว่าอยู่ที่ไหน)
Hono Framework — ทำไมเลือก Hono
Hono (แปลว่า "เปลวไฟ" ในภาษาญี่ปุ่น) คือ Web Framework ที่ออกแบบมาสำหรับ Edge Runtime โดยเฉพาะ เป็น Framework ที่เล็ก เร็ว และใช้ Web Standards API
เหตุผลที่เลือก Hono สำหรับคอร์สนี้:
- เบาและเร็ว — Bundle Size ต่ำกว่า 15KB ไม่มี Dependency ภายนอก ใช้งานได้บน Cloudflare Workers, Deno, Bun, และ Node.js
-
Web Standards API — ใช้
Request/Responseมาตรฐาน ไม่ใช่ Object แบบ Express.js ทำให้โค้ดพกพาได้ระหว่างแพลตฟอร์ม - API ที่เข้าใจง่าย — Syntax คล้าย Express.js ที่หลายคนคุ้นเคย แต่รองรับ Async/Await โดยตรงทุก Handler
- Built-in Middleware — มี Middleware สำเร็จรูปพร้อมใช้ เช่น CORS, Logger, bearerAuth, compress, cache
Express.js ใช้ req, res แบบ Node.js เดิม ส่วน Hono ใช้ c (Context)
ที่ครอบ Request และ Response มาตรฐาน เช่น
c.req.param('id') และ c.json(data)
ถ้าเคยใช้ Express มาก่อน จะปรับตัวได้เร็วมาก
Routing ใน Hono
Hono รองรับ HTTP Methods ครบถ้วนสำหรับการสร้าง REST API:
-
app.get(path, handler)— ดึงข้อมูล (Read) เช่น ดึงรายการบริการ -
app.post(path, handler)— สร้างข้อมูลใหม่ (Create) เช่น สร้างการจอง -
app.put(path, handler)— อัปเดตข้อมูลทั้งหมด (Update) เช่น แก้ไขข้อมูลบริการ -
app.delete(path, handler)— ลบข้อมูล (Delete) เช่น ยกเลิกการจอง -
app.patch(path, handler)— อัปเดตข้อมูลบางส่วน (Partial Update)
Dynamic Route Parameters: ใช้ :param ใน Path เพื่อรับค่าจาก URL
app.get('/api/services/:id', (c) => { const id = c.req.param('id'); ... })app.get('/api/users/:userId/bookings/:bookingId', (c) => { ... })— หลาย Params ได้
JSON Response: Hono มี c.json(data, statusCode) สำหรับส่ง JSON Response
โดย Status Code default คือ 200 ถ้าไม่ระบุ
REST API Convention สำหรับ BookEasy:
Method Path ทำหน้าที่
─────────────────────────────────────────────────────
GET /api/services ดึงรายการบริการทั้งหมด
GET /api/services/:id ดึงบริการเดียวตาม ID
POST /api/services สร้างบริการใหม่
PUT /api/services/:id แก้ไขบริการทั้งหมด
DELETE /api/services/:id ลบบริการ
GET /api/bookings ดึงรายการจองทั้งหมด
POST /api/bookings สร้างการจองใหม่
GET /api/bookings/:id ดึงรายละเอียดการจอง
Middleware ใน Hono
Middleware คือฟังก์ชันที่ทำงานก่อน (หรือหลัง) Route Handler ใช้สำหรับงานที่ต้องทำซ้ำทุก Request เช่น Logging, Authentication, CORS
Middleware สำคัญที่ใช้ในคอร์สนี้:
- logger() — บันทึก Log ทุก Request ที่เข้ามา แสดง Method, Path, Status, Response Time มีประโยชน์มากระหว่าง Development
-
cors() — ตั้งค่า CORS (Cross-Origin Resource Sharing) เพื่อให้ Frontend
ที่รันบน Domain อื่น (เช่น
localhost:5173) สามารถเรียก API ได้ Browser จะ Block Request ข้ามต้นทางโดย Default ถ้าไม่มี CORS Header -
bearerAuth() — ตรวจสอบ Token ใน Header
Authorization: Bearer <token>ใช้ป้องกัน Route ที่ต้องการ Authentication
ถ้าไม่เพิ่ม CORS Middleware เบราว์เซอร์จะ Block การเรียก API จาก Frontend ด้วย Error
"Access to fetch at 'http://localhost:8787' from origin 'http://localhost:5173' has been blocked by CORS policy"
ต้องตั้งค่า cors({ origin: 'http://localhost:5173' }) เสมอเมื่อ Frontend กับ Backend
รันบน Port ต่างกัน
Wrangler CLI
Wrangler คือ CLI สำหรับจัดการ Cloudflare Workers พัฒนาโดย Cloudflare เอง ใช้สำหรับ Development, Testing, และ Deploy
-
npx wrangler dev— รัน Worker ใน Local Development Mode เข้าถึงได้ที่http://localhost:8787Wrangler จะ Watch ไฟล์และ Reload อัตโนมัติเมื่อโค้ดเปลี่ยน -
npx wrangler deploy— Deploy Worker ขึ้น Cloudflare Edge Network จริง ต้องมีบัญชี Cloudflare และ Login ก่อนด้วยnpx wrangler login -
npx wrangler tail— ดู Real-time Logs ของ Worker ที่รันบน Production
ไฟล์ wrangler.toml ใน Root ของโปรเจกต์เป็นไฟล์ Config สำหรับ Wrangler
กำหนด name (ชื่อ Worker), main (Entry File), และ
compatibility_date สร้างอัตโนมัติเมื่อใช้ npm create hono@latest
# snippet 1: สร้าง Hono Worker
npm create hono@latest bookeasy-api -- --template cloudflare-workers
cd bookeasy-api
npm install
npx wrangler dev
# เปิด http://localhost:8787
// snippet 2: Hono routes พื้นฐาน — src/index.js
import { Hono } from 'hono';
import { cors } from 'hono/cors';
import { logger } from 'hono/logger';
const app = new Hono();
// Middleware
app.use('*', logger());
app.use('/api/*', cors({ origin: 'http://localhost:5173' }));
// Mock data
const SERVICES = [
{ id: 1, name: 'ตัดผมชาย', description: 'ตัดผมสไตล์เกาหลี', price: 150, duration_min: 45 },
{ id: 2, name: 'นวดแผนไทย', description: 'นวดผ่อนคลาย', price: 400, duration_min: 60 },
];
// Routes
app.get('/api/services', (c) => {
return c.json({ success: true, data: SERVICES });
});
app.get('/api/services/:id', (c) => {
const id = Number(c.req.param('id'));
const service = SERVICES.find(s => s.id === id);
if (!service) return c.json({ error: 'ไม่พบบริการ' }, 404);
return c.json({ success: true, data: service });
});
app.post('/api/bookings', async (c) => {
const body = await c.req.json();
const booking = { id: Date.now(), ...body, status: 'pending' };
return c.json({ success: true, data: booking }, 201);
});
export default app;
# snippet 3: ทดสอบ API ด้วย curl
# GET ทุก services
curl http://localhost:8787/api/services
# GET service เดี่ยว
curl http://localhost:8787/api/services/1
# POST จอง
curl -X POST http://localhost:8787/api/bookings \
-H "Content-Type: application/json" \
-d '{"service_id":1,"booking_date":"2026-07-10","booking_time":"09:00"}'
🧪 ปฏิบัติการ Lab 4 — BookEasy: สร้าง Hono API
ฝึกสร้าง Backend API ด้วย Hono บน Cloudflare Workers พร้อม Routes ครบและทดสอบด้วย curl
ต่อยอดจาก Lab 3 — สร้าง backend API ที่ frontend จะเรียกใช้ใน Week 7
สร้าง Hono project ใหม่ใน folder แยกต่างหากจาก Frontend และตรวจสอบว่า Dev Server ทำงานได้
- รันคำสั่ง
npm create hono@latest bookeasy-api -- --template cloudflare-workersใน folder เดียวกับbookeasy/ - เข้าไปใน folder ที่สร้างใหม่:
cd bookeasy-apiแล้วรันnpm install - รัน
npx wrangler devและเปิดเบราว์เซอร์ที่http://localhost:8787 - ตรวจสอบว่า Hono ตอบกลับด้วย Response (ปกติจะเห็น "Hello Hono!" หรือ JSON ว่าง ๆ)
- เปิดไฟล์
src/index.jsเพื่อดูโครงสร้างเริ่มต้น
รัน npx wrangler dev ได้โดยไม่มี Error ใน Terminal เปิด http://localhost:8787
แล้วเบราว์เซอร์แสดง Response บางอย่าง (ไม่ใช่ "Connection Refused")
ถ่ายภาพหน้าจอ Terminal ที่แสดง "Listening on http://localhost:8787"
ถ้า npm create hono@latest ถามคำถาม ให้เลือก cloudflare-workers
เป็น Template และเลือก No สำหรับ TypeScript เพื่อใช้ JavaScript ธรรมดา
Wrangler จะสร้างไฟล์ wrangler.toml ให้อัตโนมัติ ไม่ต้องแก้ไข
เขียน Routes ครบ 3 Endpoint พร้อม Mock Data และ CORS Middleware
-
แก้ไข
src/index.jsให้มี Mock DataSERVICESเป็น Array พร้อมข้อมูลบริการอย่างน้อย 2 รายการ (ดูตัวอย่างจาก Code Snippet ด้านบน) -
เพิ่ม Middleware:
app.use('*', logger())และapp.use('/api/*', cors({ origin: 'http://localhost:5173' })) -
สร้าง
GET /api/services— คืน JSON{ success: true, data: SERVICES } -
สร้าง
GET /api/services/:id— ค้นหาด้วยSERVICES.find()ถ้าไม่พบให้คืนc.json({ error: 'ไม่พบบริการ' }, 404) -
สร้าง
POST /api/bookings— รับ Body ด้วยawait c.req.json()แล้วคืน Booking Object พร้อมid: Date.now()และstatus: 'pending'ด้วย Status Code 201
รัน npx wrangler dev แล้วเรียก GET /api/services ได้ JSON ที่มี Array ของบริการ
เรียก GET /api/services/999 ได้ Response 404 พร้อม { "error": "ไม่พบบริการ" }
Terminal แสดง Log ทุกครั้งที่มี Request เข้ามา (จาก logger middleware)
ต้อง Import Middleware ก่อนใช้งาน: import { cors } from 'hono/cors' และ
import { logger } from 'hono/logger'
c.req.param('id') คืนค่าเป็น String เสมอ ต้องแปลงเป็น Number ด้วย
Number(c.req.param('id')) ก่อน Compare กับ id ใน Array ที่เป็น Number
รัน Dev Server แล้วทดสอบทุก Route ด้วย curl และบันทึก Response JSON
-
เปิด Terminal ใหม่ (ขณะที่
npx wrangler devยังรันอยู่ใน Terminal เดิม) -
ทดสอบ
GET /api/services:curl http://localhost:8787/api/services -
ทดสอบ
GET /api/services/1:curl http://localhost:8787/api/services/1 -
ทดสอบ 404:
curl http://localhost:8787/api/services/999ตรวจว่าได้ Status 404 และ{ "error": "ไม่พบบริการ" } -
ทดสอบ
POST /api/bookingsด้วย curl พร้อม JSON Body ตามตัวอย่างใน Snippet 3 - บันทึก JSON Response ของทุก Endpoint แล้วส่งเป็นหลักฐาน
ทุก Endpoint ตอบสนองถูกต้อง: GET /api/services คืน Array,
GET /api/services/1 คืน Object ของบริการ ID 1,
POST /api/bookings คืน Booking Object ที่มี id และ status: "pending"
ส่งภาพหน้าจอ Terminal ที่แสดง curl output ของทั้ง 3 Endpoint
เพิ่ม Flag -i ใน curl เพื่อดู HTTP Status Code พร้อม Response Headers ด้วย
เช่น curl -i http://localhost:8787/api/services/999
จะเห็น HTTP/1.1 404 Not Found อยู่ด้านบน
บน Windows ให้ใช้ Git Bash หรือ PowerShell แทน Command Prompt