Cara akses database di Server Component Next.js yang benar adalah query langsung dari komponen server memakai Prisma atau driver database, tanpa fetch ke Route Handler sendiri. Kode itu hanya jalan di server, jadi string koneksi tetap aman dan respons lebih cepat karena memangkas satu lapis HTTP.
// app/produk/page.tsx
import { db } from "@/lib/db";
export default async function ProdukPage() {
const produk = await db.produk.findMany({
select: { id: true, nama: true, harga: true },
take: 20,
});
return (
<ul>
{produk.map((p) => (
<li key={p.id}>{p.nama} - Rp{p.harga}</li>
))}
</ul>
);
}
Query Langsung Tanpa Fetch ke Route Sendiri
Server Component berjalan di Node.js saat request atau build, bukan di browser. Kamu bisa panggil await db.table.findMany() langsung di dalam komponen async.
- Gunakan fetch ke
/apihanya untuk client, webhook, atau pihak ketiga. - Untuk kebutuhan internal halaman, query langsung mengurangi latensi dan kode.
- Ambil kolom yang perlu saja dengan
selectagar transfer data kecil.
Langkah Akses Database di Server Component
Urutannya sederhana, tapi urutan kedua paling sering dilewatkan dan memicu error koneksi habis.
1. Simpan kredensial di ENV server tanpa prefix NEXT_PUBLIC. Contoh isi .env:
DATABASE_URL="postgresql://user:password@localhost:5432/namadb"
2. Buat client database singleton agar koneksi tidak membeludak. Simpan di file seperti lib/db.ts dan pakai ulang di semua Server Component.
import { PrismaClient } from "@prisma/client";
const globalForPrisma = globalThis as unknown as { prisma?: PrismaClient };
export const db = globalForPrisma.prisma ?? new PrismaClient();
if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = db;
3. Tulis fungsi query terpisah lalu panggil dengan await dari Server Component. Pisahkan logika SQL dari JSX agar mudah dites ulang.
4. Tangani error dan kasus data kosong. Tampilkan daftar kosong atau lempar notFound() untuk detail yang tidak ada, jangan biarkan halaman crash.
Aturan Koneksi dan Keamanan yang Wajib Dipatuhi
| Area | Aturan | Kesalahan umum |
|---|---|---|
| Import | Client DB hanya di file server | Diimpor ke Client Component |
| ENV | DATABASE_URL tanpa NEXT_PUBLIC | Kredensial bocor ke browser |
| Input | Validasi id dan filter di server | Parameter URL langsung masuk query |
- Jangan tambah
"use client"pada file yang mengimpor client database. - Kalau Client Component butuh data, oper hasil query sebagai props dari induk server.
- Untuk tulis data, gunakan Server Action dengan validasi, bukan query langsung dari event klik.
FAQ
Apakah perlu Route Handler untuk baca database?
Tidak. Baca langsung dari Server Component untuk render halaman.
Kenapa koneksi database habis saat dev?
Hot reload membuat PrismaClient baru tiap simpan file, pola singleton di atas mencegahnya.
Apakah data database ikut ter-cache?
Bisa, tergantung cara fetch dan konfigurasi route. Atur revalidasi hanya kalau datanya memang jarang berubah.