Cara Membuat API Backend dengan NitroJs

Ashley Goolam

Ashley Goolam

19 January 2026

Cara Membuat API Backend dengan NitroJs

Ketika saya membangun API produksi pertama saya, saya menggunakan Express.js dan pengaturannya memakan waktu sekitar dua jam: boilerplate, middleware, route handler, konfigurasi TypeScript, dan skrip penerapan. Baru-baru ini, saya berhasil merilis REST API lengkap hanya dalam 20 menit menggunakan NitroJs. Tanpa rantai app.use(), tanpa routing manual, tanpa pusing masalah penerapan.

Panduan ini menunjukkan bagaimana NitroJs menghilangkan boilerplate sambil memberikan Anda backend siap produksi yang berjalan di mana saja, Node, Bun, Deno, serverless, atau edge.

Apa Itu NitroJs dan Mengapa Menggunakannya untuk API Backend?

NitroJs adalah toolkit server dari ekosistem UnJS yang memperlakukan backend Anda sebagai artefak build. Alih-alih menulis server yang terikat pada runtime, Anda menulis route handler dan Nitro mengompilasinya menjadi bundel portabel. Terapkan kode yang sama ke Node.js, Cloudflare Workers, Vercel, atau kontainer Docker tanpa mengubah satu baris pun.

NitroJs untuk API Backend

Model mental inti: Tulis rute, bukan server. Anda fokus pada logika API; Nitro menangani HTTP, middleware, dan koneksi platform.

Keunggulan utama untuk API backend:

Bagi pengembang API, ini berarti Anda merilis lebih cepat dan lebih sedikit melakukan refaktor saat mengubah infrastruktur.

button

Memulai: Instal NitroJs dalam 5 Menit

Langkah 1: Menyiapkan Proyek

# Menggunakan pnpm (disarankan)
pnpm dlx giget@latest nitro nitro-api-backend

# Atau npm
npm create nitro@latest nitro-api-backend

# Atau bun
bunx giget@latest nitro nitro-api-backend

Ini mengkloning template starter resmi ke dalam nitro-api-backend.

Langkah 2: Menjelajahi Struktur

cd nitro-api-backend
tree -L 2

Output:

├── server
│   ├── api
│   ├── routes
│   ├── tasks
│   └── middleware
├── nitro.config.ts
├── package.json
└── tsconfig.json

Direktori penting:

Untuk API backend murni, abaikan routes dan letakkan semuanya di api.

Langkah 3: Menjalankan Server Pengembangan

pnpm install
pnpm dev

Nitro dimulai di http://localhost:3000 dengan hot reload. Edit berkas, dan server akan dimulai ulang dalam waktu kurang dari 200ms.

memulai dengan NitroJs

Membangun Endpoint API Pertama Anda

Penangan GET Sederhana

Buat 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 secara otomatis menyajikan ini di GET /api/users. Pembungkus defineEventHandler menyediakan keamanan tipe dan akses ke konteks permintaan.

Rute Dinamis dengan Parameter

Buat 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`
  };
});

Akses GET /api/users/42 untuk melihat { id: 42, name: "User 42", ... }.

Permintaan POST dengan Badan JSON

Buat server/api/users.post.ts:

// server/api/users.post.ts
export default defineEventHandler(async (event) => {
  const body = await readBody(event);
  
  // Nitro secara otomatis mengurai JSON
  const { name, email } = body;
  
  if (!name || !email) {
    throw createError({
      statusCode: 422,
      statusMessage: 'Name and email are required'
    });
  }
  
  // Mensimulasikan penyisipan database
  const newUser = {
    id: Math.floor(Math.random() * 1000),
    name,
    email,
    createdAt: new Date().toISOString()
  };
  
  return newUser;
});

Uji ini:

curl -X POST http://localhost:3000/api/users \
  -H "Content-Type: application/json" \
  -d '{"name":"Charlie","email":"charlie@example.com"}'

Respons Aman Tipe

Nitro menginferensi tipe respons dari nilai kembalian Anda. Untuk kontrak yang ketat, gunakan tipe eksplisit:

// 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 }
  ];
});

Sekarang klien yang mengimpor endpoint ini mendapatkan IntelliSense penuh.

Pola API Tingkat Lanjut

Middleware untuk Otentikasi

Buat 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'
      });
    }
  }
});

Middleware berjalan sebelum setiap rute. Tambahkan ke nitro.config.ts:

// nitro.config.ts
export default defineNitroConfig({
  srcDir: 'server',
  runtimeConfig: {
    apiSecret: process.env.API_SECRET
  }
});

Melakukan Caching Respons API

Cache komputasi mahal selama 60 detik:

// 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, // detik
  name: 'stats',
  getKey: () => 'global-stats'
});

Nitro menangani invalidasi cache dan penyimpanan (memori, Redis, atau Cloudflare KV berdasarkan target penerapan).

Penanganan Unggah Berkas

// server/api/upload.post.ts
export default defineEventHandler(async (event) => {
  const files = await readMultipartFormData(event);
  
  if (!files?.length) {
    throw createError({ statusCode: 400, statusMessage: 'No files uploaded' });
  }
  
  const storage = useStorage('uploads');
  const file = files[0];
  
  await storage.setItem(file.filename, file.data);
  
  return { success: true, filename: file.filename };
});

Uji dengan:

curl -X POST http://localhost:3000/api/upload \
  -F "file=@/path/to/image.jpg"

Penerapan: Dari Lokal ke Produksi

Membangun untuk Produksi

pnpm build

Nitro menghasilkan direktori .output dengan titik masuk khusus platform.

Menjalankan di Node.js

node .output/server/index.mjs

Tidak diperlukan node_modules—build mengemas semuanya.

Menerapkan ke Cloudflare Workers

# Instal preset
pnpm add -D nitro-preset-cloudflare-workers

# Build dengan preset
NITRO_PRESET=cloudflare-workers pnpm build

# Terapkan
wrangler deploy .output

Menerapkan ke Vercel (Tanpa Server)

# Vercel mendeteksi Nitro secara otomatis
vercel

Atau konfigurasikan nitro.config.ts:

export default defineNitroConfig({
  preset: 'vercel-edge'
});

Variabel Lingkungan

Buat .env secara lokal, lalu gunakan dasbor platform di produksi:

# .env
API_SECRET=dev-secret-key
DATABASE_URL=file:./dev.db

Akses di handler:

const config = useRuntimeConfig();
const secret = config.apiSecret;

Kasus Penggunaan Lanjutan

WebSockets & Server-Sent Events

Nitro mendukung WebSockets melalui defineWebSocketHandler:

// server/api/ws.ts
export default defineWebSocketHandler({
  open(peer) {
    console.log('WebSocket terhubung:', peer);
  },
  message(peer, message) {
    peer.send(`Echo: ${message.text()}`);
  },
  close(peer, details) {
    console.log('WebSocket ditutup:', details);
  }
});

Akses di ws://localhost:3000/api/ws.

Tugas Latar Belakang

Buat 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('Pembersihan selesai');
});

Ini berjalan setiap hari pukul 2 pagi. Terapkan ke platform dengan dukungan cron (misalnya, Vercel, Netlify).

Mesin Alur Kerja

Integrasikan dengan useWorkflow.dev untuk orkestrasi kompleks:

// 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: 'dimulai' };
});

Skenario Pengembang Nyata

Skenario 1: Backend Situs Statis

Terapkan Nitro API ke Cloudflare Workers yang menyajikan data JSON ke situs JAMstack statis. Tingkat gratis menangani 100 ribu permintaan/hari.

Skenario 2: API Aplikasi Seluler

Bangun endpoint REST untuk aplikasi React Native. Gunakan penanganan CORS bawaan Nitro:

// nitro.config.ts
export default defineNitroConfig({
  routeRules: {
    '/api/**': { cors: true }
  }
});

Skenario 3: Gateway Microservices

Jalankan Nitro sebagai gateway API yang mengagregasi microservices. Gunakan $fetch untuk memproksi permintaan:

// 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 };
});

Uji API NitroJs Anda dengan Apidog

Nitro menghasilkan backend dengan cepat, tetapi kecepatan tidak berarti apa-apa jika endpoint Anda rusak. Saat Anda merilis POST /api/users baru, impor definisi rute ke Apidog. Ini merekayasa balik tipe kembalian handler Anda dan secara otomatis menghasilkan tes kontrak.

Pengujian Kontrak API dengan Apidog
button

Jalankan di CI untuk menangkap perubahan yang merusak sebelum tim frontend Anda frustrasi. Gratis untuk memulai, dan itu adalah batasan yang dibutuhkan pengembangan Nitro Anda yang cepat.

Pertanyaan yang Sering Diajukan

1. Bisakah Nitro menggantikan Express.js sepenuhnya?
Ya. Nitro menangani routing, middleware, dan penerapan dengan lebih baik. Migrasi dengan memindahkan middleware Express ke plugin Nitro dan rute ke server/api/.

2. Bagaimana Nitro menangani koneksi database?
Gunakan plugin Nitro untuk menginisialisasi pool saat startup. Lapisan penyimpanan mengabstraksi caching, tetapi untuk SQL, gunakan ORM Anda sendiri (Prisma, Drizzle).

3. Apakah Nitro siap produksi?
Tentu saja. Nuxt menggunakan Nitro untuk jutaan situs produksi. Ini sudah teruji dalam skala besar.

4. Bisakah saya menggunakan Nitro dengan GraphQL?
Ya. Tambahkan handler GraphQL di server/api/graphql.post.ts. Gunakan pustaka GraphQL Node apa pun—Nitro tidak membatasi Anda.

5. Apa perbedaan antara Nitro dan Hono?
Hono adalah router yang ringan. Nitro adalah toolkit server lengkap dengan build, preset, dan penyimpanan. Gunakan Hono untuk microservices, Nitro untuk backend lengkap.

Kesimpulan

NitroJs memikirkan ulang pengembangan backend dengan mengompilasi API Anda menjadi artefak portabel. Anda mendapatkan routing sistem berkas, keamanan TypeScript, dan penerapan universal tanpa boilerplate. Bangun REST API Anda berikutnya dengan Nitro, dan validasi dengan Apidog. Anda di masa depan akan berterima kasih ketika Anda bermigrasi dari Node ke edge hanya dengan satu baris konfigurasi.

button

Mengembangkan API dengan Apidog

Apidog adalah alat pengembangan API yang membantu Anda mengembangkan API dengan lebih mudah dan efisien.