Pendahuluan
Nuxt 3 menyediakan Nitro sebagai runtime server yang secara otomatis menangani kompilasi API internal. Ketika aplikasi membutuhkan endpoint backend sederhana, Nitro membuat pembuatan API internal menjadi efisien tanpa menambahkan projek terpisah. Artikel ini membahas cara menyusun server API di Nuxt 3, mulai dari struktur folder, request handling, validasi input, sampai integrasi dengan database atau layanan lain.
Struktur Folder server/api
Di project Nuxt 3, Nitro mengumpulkan semua file di server/api dan menganggapnya sebagai route API. Setiap file merepresentasikan route berdasarkan struktur folder:
server/api/users.get.tsmenjadiGET /api/usersserver/api/products/[id].post.tsmenjadiPOST /api/products/:idserver/api/admin/metrics.get.tsjadiGET /api/admin/metrics
Selain folder, Anda dapat mengganti method HTTP dengan ekstensi file (.get.ts, .post.ts, .put.ts, .delete.ts). Ini membuat navigasi dan konvensi route mudah dipahami. Untuk route dinamis, gunakan parameter dalam nama folder/file seperti [userId].
Handling Request dan Response
Nitro menyediakan helper seperti defineEventHandler untuk menangani request. Event handler menerima objek request dan response bawaan Node.js tetapi disederhanakan. Sebagai contoh:
import { defineEventHandler } from 'h3'
export default defineEventHandler(async (event) => {
const { req, res } = event
const params = getQuery(event)
return {
message: 'API nuxt internal aktif',
params
}
})Gunakan getQuery untuk mengambil query params dan readBody untuk payload JSON. Result handler dapat berupa data, promise, atau createError untuk raise error. Hasilnya akan otomatis di-serialize menjadi JSON.
Query Params dan Body Validation
Untuk query params, Nuxt/Nitro tidak menyediakan schema validation bawaan. Kode contoh berikut menunjukkan bagaimana memeriksa keberadaan parameter:
import { defineEventHandler, sendError } from 'h3'
export default defineEventHandler((event) => {
const { id } = getQuery(event)
if (!id) {
return sendError(event, createError({ statusCode: 400, statusMessage: 'Parameter id dibutuhkan' }))
}
return { id }
})Untuk validation body, gunakan library seperti zod atau @hapi/joi. Contoh dengan zod:
import { defineEventHandler } from 'h3'
import { z } from 'zod'
const userSchema = z.object({
name: z.string().min(3),
email: z.string().email()
})
export default defineEventHandler(async (event) => {
const body = await readBody(event)
const parsed = userSchema.safeParse(body)
if (!parsed.success) {
return createError({ statusCode: 422, statusMessage: JSON.stringify(parsed.error.issues) })
}
return { data: parsed.data }
})Dengan pendekatan ini, developer mengetahui kesalahan input segera dan response jelas.
Environment Variables di Nitro
Environment variables dikelola lewat file .env atau .env.defaults. Nuxt 3 menyediakan useRuntimeConfig() untuk mengakses nilai tersebut dengan aman:
export default defineNuxtConfig({
runtimeConfig: {
public: {
apiBase: '/api'
},
dbUrl: process.env.DB_URL
}
})Di server API:
const runtimeConfig = useRuntimeConfig()
const dbUrl = runtimeConfig.dbUrlKarena environment variables tidak ditransfer ke client kecuali di bawah runtimeConfig.public, Anda dapat menyimpan credential sensitif dengan aman.
Koneksi ke Database atau Service Eksternal
Server API Nuxt cocok bila butuh integrasi langsung ke database atau layanan lain tanpa perlu server terpisah. Contoh menghubungkan Prisma:
import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient()
export default defineEventHandler(() => {
return prisma.user.findMany()
})Pastikan initialization Prisma hanya sekali (misal di file global) agar tidak menimbulkan koneksi berlebih saat hot reload. Anda juga bisa menghubungkan service lain seperti API internal, Redis, atau message queue dengan pola serupa.
Contoh Endpoint CRUD Sederhana
Berikut struktur API CRUD untuk entitas task:
GET /api/tasks– Fetch semua taskPOST /api/tasks– Buat task baruPUT /api/tasks/[id]– Update taskDELETE /api/tasks/[id]– Hapus task
Contoh implentasi request POST:
import { defineEventHandler, sendError } from 'h3'
export default defineEventHandler(async (event) => {
const body = await readBody(event)
if (!body.title) {
return sendError(event, createError({ statusCode: 400, statusMessage: 'Title wajib diisi' }))
}
const task = await prisma.task.create({
data: {
title: body.title,
done: false
}
})
return task
})Gunakan modular logic agar handler tetap bersih, misal memisahkan service layer atau repository untuk operasi database.
Error Handling dan Logging Dasar
Gunakan createError atau sendError dari h3 untuk menormalkan response error:
import { defineEventHandler, createError } from 'h3'
export default defineEventHandler(() => {
try {
// operasi yang mungkin gagal
} catch (err) {
throw createError({ statusCode: 500, statusMessage: err.message })
}
})Untuk logging, gunakan console atau integrasi logger (misal winston). Contoh sederhana:
console.info('Request diterima', { path: event.node.req.url })
console.error('Database error', err)Selalu sertakan informasi seperti method, path, dan status saat log error. Untuk produksi, arahkan log ke service observabilitas.
Kapan Memilih Server API Nuxt vs Backend Terpisah
Server API Nuxt ideal jika:
- Aplikasi Anda membutuhkan API sederhana untuk CRUD internal atau data caching.
- Anda menginginkan deployment tunggal tanpa sinkronisasi versi frontend/backend.
- Data access terbatas dan latensi rendah menjadi prioritas.
Sementara backend terpisah lebih tepat jika:
- Ada kebutuhan otorisasi kompleks, microservices, atau trafik tinggi.
- Anda perlu reuse API di banyak klien (mobile, microservices).
- Tim backend ingin lifecycle independen dari UI.
Memilih nitro server API berarti kompromi antara kemudahan integrasi dengan Nuxt terhadap skalabilitas. Untuk aplikasi kecil sampai menengah, Nitro menawarkan produktivitas tinggi. Untuk use-case enterprise dengan kebutuhan distribusi, pertimbangkan backend terpisah.
Kesimpulan
Nitro di Nuxt 3 menyederhanakan pembuatan API internal. Dengan struktur server/api, kita bisa menangani query, validasi, environment variables, koneksi database, dan logging tanpa setup terpisah. Pastikan menerapkan validating dan error handling agar endpoint tetap aman dan dapat di-debug. Gunakan server API Nuxt ketika kebutuhan backend tidak rumit dan Anda ingin kemudahan deployment; pilih backend terpisah saat skalabilitas atau reuse menjadi fokus utama.
Komentar
0 komentar
Masuk ke akun kamu untuk ikut berkomentar.
Belum ada komentar
Jadilah yang pertama ikut berdiskusi!