เมื่อผมสร้าง API ที่ใช้งานจริงครั้งแรก ผมใช้ Express.js และใช้เวลาติดตั้งประมาณสองชั่วโมง: โค้ดเริ่มต้น, มิดเดิลแวร์, แฮนเดอร์เส้นทาง, การกำหนดค่า TypeScript และสคริปต์การดีพลอย เมื่อเร็วๆ นี้ ผมได้สร้าง REST API ที่สมบูรณ์ได้ในเวลาเพียง 20 นาทีโดยใช้ NitroJs ไม่มีการเชื่อมโยง app.use(), ไม่มีการกำหนดเส้นทางด้วยตนเอง, ไม่มีปัญหาในการดีพลอย
คู่มือนี้จะแสดงให้คุณเห็นว่า NitroJs ช่วยลดโค้ดเริ่มต้นได้อย่างไร พร้อมมอบแบ็กเอนด์ที่พร้อมใช้งานจริง ซึ่งทำงานได้ทุกที่ ไม่ว่าจะเป็น Node, Bun, Deno, serverless หรือ edge
NitroJs คืออะไร และทำไมจึงควรใช้สำหรับแบ็กเอนด์ API?
NitroJs เป็นชุดเครื่องมือเซิร์ฟเวอร์จาก ระบบนิเวศ UnJS ที่ถือว่าแบ็กเอนด์ของคุณเป็น build artifact แทนที่จะเขียนเซิร์ฟเวอร์ที่ผูกติดกับรันไทม์ คุณเขียนแฮนเดอร์เส้นทางและ Nitro จะคอมไพล์เป็นชุดรวมที่พกพาได้ สามารถดีพลอยโค้ดเดียวกันไปยัง Node.js, Cloudflare Workers, Vercel หรือคอนเทนเนอร์ Docker ได้โดยไม่ต้องเปลี่ยนแม้แต่บรรทัดเดียว

โมเดลหลัก: เขียนเส้นทาง ไม่ใช่เซิร์ฟเวอร์ คุณมุ่งเน้นที่ตรรกะของ API; Nitro จัดการ HTTP, มิดเดิลแวร์ และส่วนเชื่อมต่อแพลตฟอร์ม
ข้อดีหลักสำหรับแบ็กเอนด์ API:
- กำหนดค่าเป็นศูนย์: ไม่มีโค้ดเริ่มต้น
server.js - การกำหนดเส้นทางตามระบบไฟล์:
routes/users.get.tsกลายเป็นGET /users - รองรับ TypeScript โดยกำเนิด: การอนุมานประเภทอัตโนมัติจากแฮนเดอร์
- การดีพลอยแบบสากล: หนึ่งบิลด์ รองรับหลายเป้าหมาย
- การแคชในตัว: จัดเก็บการตอบสนอง API ในหน่วยความจำ, Redis หรือ Cloudflare KV
- เลเยอร์จัดเก็บข้อมูล: ระบบไฟล์แบบนามธรรมสำหรับข้อมูลชั่วคราว
สำหรับนักพัฒนา API นี่หมายความว่าคุณสามารถส่งมอบงานได้เร็วขึ้นและปรับโครงสร้างโค้ดน้อยลงเมื่อเปลี่ยนโครงสร้างพื้นฐาน
เริ่มต้น: ติดตั้ง NitroJs ใน 5 นาที
ขั้นตอนที่ 1: สร้างโครงสร้างโปรเจกต์
# ใช้ pnpm (แนะนำ)
pnpm dlx giget@latest nitro nitro-api-backend
# หรือ npm
npm create nitro@latest nitro-api-backend
# หรือ bun
bunx giget@latest nitro nitro-api-backend
นี่เป็นการโคลนเทมเพลตเริ่มต้นอย่างเป็นทางการไปยัง nitro-api-backend
ขั้นตอนที่ 2: สำรวจโครงสร้าง
cd nitro-api-backend
tree -L 2
ผลลัพธ์:
├── server
│ ├── api
│ ├── routes
│ ├── tasks
│ └── middleware
├── nitro.config.ts
├── package.json
└── tsconfig.json
ไดเรกทอรีที่สำคัญ:
server/api/: เส้นทาง API (ไม่มี UI)server/routes/: เส้นทาง Full-stack (สำหรับ SSR)server/middleware/: มิดเดิลแวร์ส่วนกลางserver/tasks/: งานเบื้องหลัง
สำหรับ API แบ็กเอนด์ล้วนๆ ให้ละเว้น routes และใส่ทุกอย่างไว้ใน api
ขั้นตอนที่ 3: รันเซิร์ฟเวอร์สำหรับพัฒนา
pnpm install
pnpm dev
Nitro จะเริ่มทำงานที่ http://localhost:3000 พร้อม hot reload เมื่อแก้ไขไฟล์ เซิร์ฟเวอร์จะรีสตาร์ทในเวลาไม่ถึง 200ms

การสร้าง API Endpoint แรกของคุณ
แฮนเดอร์ GET แบบง่าย
สร้าง server/api/users.get.ts:
// server/api/users.get.ts
export default defineEventHandler(() => {
return [
{ id: 1, name: "Alice", email: "alice@example.com" },
{ id: 2, name: "Bob", email: "bob@example.com" }
];
});
Nitro จะให้บริการนี้ที่ GET /api/users โดยอัตโนมัติ ตัว wrapper defineEventHandler ช่วยให้มั่นใจเรื่องความปลอดภัยของประเภทข้อมูลและสามารถเข้าถึง context ของคำขอได้
เส้นทางไดนามิกพร้อมพารามิเตอร์
สร้าง server/api/users/[id].get.ts:
// server/api/users/[id].get.ts
export default defineEventHandler((event) => {
const id = getRouterParam(event, 'id');
if (!id) {
throw createError({
statusCode: 400,
statusMessage: 'User ID is required'
});
}
return {
id: Number(id),
name: `User ${id}`,
email: `user${id}@example.com`
};
});
เข้าถึง GET /api/users/42 เพื่อดู { id: 42, name: "User 42", ... }
POST พร้อม JSON Body
สร้าง server/api/users.post.ts:
// server/api/users.post.ts
export default defineEventHandler(async (event) => {
const body = await readBody(event);
// Nitro แยกวิเคราะห์ JSON โดยอัตโนมัติ
const { name, email } = body;
if (!name || !email) {
throw createError({
statusCode: 422,
statusMessage: 'Name and email are required'
});
}
// จำลองการแทรกข้อมูลลงในฐานข้อมูล
const newUser = {
id: Math.floor(Math.random() * 1000),
name,
email,
createdAt: new Date().toISOString()
};
return newUser;
});
ทดสอบโดยใช้:
curl -X POST http://localhost:3000/api/users \
-H "Content-Type: application/json" \
-d '{"name":"Charlie","email":"charlie@example.com"}'
การตอบสนองที่ปลอดภัยด้านประเภทข้อมูล (Type-Safe)
Nitro อนุมานประเภทการตอบสนองจากค่าที่ส่งคืนของคุณ สำหรับสัญญาที่เข้มงวด ให้ใช้ประเภทข้อมูลที่ชัดเจน:
// server/api/products.get.ts
interface Product {
id: number;
name: string;
price: number;
inStock: boolean;
}
export default defineEventHandler<Product[]>(() => {
return [
{ id: 1, name: "Laptop", price: 1299.99, inStock: true },
{ id: 2, name: "Mouse", price: 29.99, inStock: false }
];
});
ตอนนี้ไคลเอ็นต์ที่อิมพอร์ต endpoint นี้จะได้รับ IntelliSense เต็มรูปแบบ
รูปแบบ API ขั้นสูง
มิดเดิลแวร์สำหรับการตรวจสอบสิทธิ์
สร้าง server/middleware/auth.ts:
// server/middleware/auth.ts
export default defineEventHandler(async (event) => {
const protectedRoutes = ['/api/admin', '/api/users/me'];
if (protectedRoutes.some(route => event.path.startsWith(route))) {
const token = getHeader(event, 'authorization')?.replace('Bearer ', '');
if (!token || token !== process.env.API_SECRET) {
throw createError({
statusCode: 401,
statusMessage: 'Unauthorized'
});
}
}
});
มิดเดิลแวร์ทำงานก่อนทุกเส้นทาง เพิ่มลงใน nitro.config.ts:
// nitro.config.ts
export default defineNitroConfig({
srcDir: 'server',
runtimeConfig: {
apiSecret: process.env.API_SECRET
}
});
การแคชการตอบสนอง API
แคชการคำนวณที่ใช้เวลานานเป็นเวลา 60 วินาที:
// server/api/stats.get.ts
export default defineCachedEventHandler(async () => {
const db = useStorage('data');
const users = await db.getItem('users') || [];
return {
totalUsers: users.length,
activeUsers: users.filter(u => u.lastSeen > Date.now() - 86400000).length
};
}, {
maxAge: 60, // วินาที
name: 'stats',
getKey: () => 'global-stats'
});
Nitro จัดการการล้างแคชและการจัดเก็บข้อมูล (หน่วยความจำ, Redis หรือ Cloudflare KV ตามเป้าหมายการดีพลอย)
การจัดการการอัปโหลดไฟล์
// server/api/upload.post.ts
export default defineEventHandler(async (event) => {
const files = await readMultipartFormData(event);
if (!files?.length) {
throw createError({ statusCode: 400, statusMessage: 'ไม่พบไฟล์ที่อัปโหลด' });
}
const storage = useStorage('uploads');
const file = files[0];
await storage.setItem(file.filename, file.data);
return { success: true, filename: file.filename };
});
ทดสอบด้วย:
curl -X POST http://localhost:3000/api/upload \
-F "file=@/path/to/image.jpg"
การดีพลอย: จาก Local สู่ Production
สร้างสำหรับ Production
pnpm build
Nitro สร้างไดเรกทอรี .output พร้อม entry points เฉพาะแพลตฟอร์ม
รันบน Node.js
node .output/server/index.mjs
ไม่จำเป็นต้องมี node_modules—บิลด์จะรวมทุกอย่างไว้ด้วยกัน
ดีพลอยไปยัง Cloudflare Workers
# ติดตั้ง preset
pnpm add -D nitro-preset-cloudflare-workers
# สร้างด้วย preset
NITRO_PRESET=cloudflare-workers pnpm build
# ดีพลอย
wrangler deploy .output
ดีพลอยไปยัง Vercel (Serverless)
# Vercel ตรวจจับ Nitro โดยอัตโนมัติ
vercel
หรือกำหนดค่า nitro.config.ts:
export default defineNitroConfig({
preset: 'vercel-edge'
});
ตัวแปรสภาพแวดล้อม
สร้าง .env ในเครื่องของคุณ จากนั้นใช้แดชบอร์ดแพลตฟอร์มในการผลิต:
# .env
API_SECRET=dev-secret-key
DATABASE_URL=file:./dev.db
เข้าถึงได้ในแฮนเดอร์:
const config = useRuntimeConfig();
const secret = config.apiSecret;
กรณีการใช้งานขั้นสูง
WebSockets & Server-Sent Events
Nitro รองรับ WebSockets ผ่าน defineWebSocketHandler:
// server/api/ws.ts
export default defineWebSocketHandler({
open(peer) {
console.log('WebSocket เชื่อมต่อแล้ว:', peer);
},
message(peer, message) {
peer.send(`Echo: ${message.text()}`);
},
close(peer, details) {
console.log('WebSocket ปิดแล้ว:', details);
}
});
เข้าถึงได้ที่ ws://localhost:3000/api/ws
งานเบื้องหลัง
สร้าง server/tasks/cleanup.ts:
// server/tasks/cleanup.ts
export default defineCronHandler('0 2 * * *', async () => {
const db = useStorage('temp');
const keys = await db.getKeys();
for (const key of keys) {
const metadata = await db.getMeta(key);
if (metadata.expiresAt < Date.now()) {
await db.removeItem(key);
}
}
console.log('การล้างข้อมูลเสร็จสมบูรณ์');
});
สิ่งนี้จะทำงานทุกวันเวลา 02:00 น. ดีพลอยไปยังแพลตฟอร์มที่รองรับ cron (เช่น Vercel, Netlify)
เอนจินเวิร์กโฟลว์
ผสานรวมกับ useWorkflow.dev สำหรับการจัดระบบที่ซับซ้อน:
// server/api/workflows/process.ts
import { createWorkflow } from '@useworkflow/sdk';
export default defineEventHandler(async (event) => {
const workflow = createWorkflow('data-pipeline', {
steps: [
{ id: 'fetch', run: 'https://api.example.com/data' },
{ id: 'transform', run: 'transform.js' },
{ id: 'store', run: async (data) => {
const storage = useStorage('results');
await storage.setItem('latest', data);
}}
]
});
await workflow.start();
return { status: 'เริ่มแล้ว' };
});
สถานการณ์จำลองสำหรับนักพัฒนาจริง
สถานการณ์ที่ 1: แบ็กเอนด์ของ Static Site
ดีพลอย Nitro API ไปยัง Cloudflare Workers ที่ให้บริการข้อมูล JSON แก่เว็บไซต์ JAMstack แบบคงที่ (static) โดย tier ฟรีรองรับ 100K คำขอต่อวัน
สถานการณ์ที่ 2: API สำหรับแอปพลิเคชันมือถือ
สร้าง REST endpoint สำหรับแอป React Native ใช้การจัดการ CORS ในตัวของ Nitro:
// nitro.config.ts
export default defineNitroConfig({
routeRules: {
'/api/**': { cors: true }
}
});
สถานการณ์ที่ 3: Microservices Gateway
รัน Nitro เป็น API gateway ที่รวมไมโครเซอร์วิสต่างๆ ใช้ $fetch เพื่อเป็นพร็อกซีคำขอ:
// server/api/aggregate.get.ts
export default defineEventHandler(async (event) => {
const [users, posts] = await Promise.all([
$fetch('https://users-service.internal/users'),
$fetch('https://posts-service.internal/posts')
]);
return { users, posts };
});
ทดสอบ NitroJs API ของคุณด้วย Apidog
Nitro สร้างแบ็กเอนด์ได้อย่างรวดเร็ว แต่ความเร็วก็ไม่มีความหมายหาก endpoint ของคุณเสีย เมื่อคุณส่งมอบ POST /api/users ใหม่ ให้นำนิยามเส้นทางเข้าสู่ Apidog ซึ่งจะทำการ reverse-engineer ประเภทการคืนค่าของแฮนเดอร์ของคุณ และสร้างการทดสอบสัญญาโดยอัตโนมัติ

รันการทดสอบใน CI เพื่อตรวจจับการเปลี่ยนแปลงที่ทำให้เกิดข้อผิดพลาด ก่อนที่ทีมส่วนหน้าของคุณจะปวดหัว เริ่มต้นใช้งานได้ฟรี และเป็นรั้วป้องกันที่การพัฒนา Nitro ที่รวดเร็วของคุณต้องการ
คำถามที่พบบ่อย
1. Nitro สามารถแทนที่ Express.js ได้ทั้งหมดหรือไม่?
ได้ Nitro จัดการการกำหนดเส้นทาง, มิดเดิลแวร์, และการดีพลอยได้ดีกว่า ทำการย้ายโดยการย้ายมิดเดิลแวร์ Express ไปยังปลั๊กอิน Nitro และเส้นทางไปยัง server/api/
2. Nitro จัดการการเชื่อมต่อฐานข้อมูลอย่างไร?
ใช้ปลั๊กอิน Nitro เพื่อเริ่มต้น pools เมื่อเริ่มทำงาน เลเยอร์จัดเก็บข้อมูลจะแยกส่วนการแคชออก แต่สำหรับ SQL คุณต้องนำ ORM ของคุณเอง (Prisma, Drizzle) มาใช้
3. Nitro พร้อมสำหรับการใช้งานจริงแล้วหรือยัง?
แน่นอน Nuxt ใช้ Nitro สำหรับเว็บไซต์ production หลายล้านแห่ง มันถูกทดสอบแล้วสำหรับการใช้งานในขนาดใหญ่
4. ฉันสามารถใช้ Nitro กับ GraphQL ได้หรือไม่?
ได้ เพิ่ม GraphQL handler ใน server/api/graphql.post.ts ใช้ไลบรารี Node GraphQL ใดก็ได้—Nitro ไม่ได้จำกัดคุณ
5. ความแตกต่างระหว่าง Nitro กับ Hono คืออะไร?
Hono เป็นเราเตอร์น้ำหนักเบา ส่วน Nitro เป็นชุดเครื่องมือเซิร์ฟเวอร์ที่สมบูรณ์พร้อมบิลด์, presets และพื้นที่จัดเก็บข้อมูล ใช้ Hono สำหรับไมโครเซอร์วิส ใช้ Nitro สำหรับแบ็กเอนด์แบบเต็มรูปแบบ
สรุป
NitroJs ได้ปฏิวัติการพัฒนาแบ็กเอนด์โดยการคอมไพล์ API ของคุณให้เป็น build artifact ที่พกพาได้ คุณจะได้รับการกำหนดเส้นทางตามระบบไฟล์, ความปลอดภัยของ TypeScript, และการดีพลอยแบบสากลโดยไม่มีโค้ดเริ่มต้น สร้าง REST API ถัดไปของคุณด้วย Nitro และตรวจสอบความถูกต้องด้วย Apidog อนาคตของคุณจะขอบคุณเมื่อคุณย้ายจาก Node ไปยัง edge ได้ด้วยการกำหนดค่าเพียงบรรทัดเดียว
