Bongkar Pemicu Render Dinamis dan Cara Mengatasi Dynamic Server Usage Next Js

Pesan dynamic server usage muncul karena halaman yang Next.js coba render statis ternyata memanggil fungsi dinamis. Perbaikannya bukan mematikan cache, melainkan mengisolasi pemicu itu ke batas dinamis yang kecil, lalu membiarkan sisa halaman tetap statis.

Penyebab Dynamic Server Usage di App Router

App Router melakukan prerender secara default. Saat proses itu menyentuh cookies(), headers(), atau searchParams, Next.js menghentikan prerender dan menandai route sebagai dinamis. Build tetap jalan, tetapi halaman tidak lagi statis.

Fungsi yang membaca request pengguna selalu memaksa hasil dinamis. Masalah muncul ketika fungsi itu berada di layout atau page level atas, sehingga seluruh segmen ikut menjadi dinamis.

  • cookies() dan headers() dari next/headers
  • searchParams di Page atau useSearchParams() di Client Component
  • Date.now(), Math.random(), dan new Date() saat render
  • fetch dengan no-store atau revalidate: 0
  • pembacaan token auth atau locale per request di Server Component atas

Tabel Diagnosis Dynamic Server Usage Next Js

Baca log npm run build sampai baris yang menyebut nama file dan fungsi, misalnya cookies() accessed at app/dashboard/page.tsx. Baris itu menunjukkan lokasi sebenarnya, bukan halaman yang dilaporkan error.

Gejala Penyebab Arah Solusi
Build gagal saat prerender /dashboard cookies() di page utama pindah ke komponen anak tersendiri
Route statis berubah jadi dinamis headers() di layout turunkan ke komponen yang butuh saja
Error hanya di useSearchParams() tanpa batas Suspense b Bungkus dengan Suspense

Bedakan dua kondisi ini. Error prerender menghentikan build dan wajib diperbaiki. Penanda ƒ Dynamic di output route tanpa build gagal berarti halaman memang dinamis secara normal.

Cara Mengatasi Dynamic Server Usage Next Js Langkah per Langkah

Jangan langsung memakai dynamic = force-dynamic atau menempel use client di page. Keduanya menyembunyikan masalah dan membuat seluruh route dinamis.

  1. Salin pesan build lengkap dan catat file serta fungsi pemicunya.
  2. Pindahkan pemicu ke komponen Server Component kecil, misalnya UserMenu, bukan seluruh page.
  3. Jika datanya hanya untuk interaksi browser, pindahkan ke Client Component dengan batas Suspense.
  4. Jika datanya untuk API, pindahkan ke Route Handler dan panggil lewat fetch.
  5. Jalankan ulang npm run build dan pastikan hanya segmen kecil yang bertanda dinamis.
// Bermasalah: seluruh page jadi dinamis
import { cookies } from "next/headers";

export default function Page() {
  const theme = cookies().get("theme")?.value ?? "light";
  return <main>{theme}</main>;
}

// Perbaikan: isolasi + tandai segmen kecil
// app/dashboard/_components/ThemeLabel.tsx
import { cookies } from "next/headers";

export function ThemeLabel() {
  const theme = cookies().get("theme")?.value ?? "light";
  return <span>{theme}</span>;
}

Tambahkan export const dynamic = “force-dynamic” hanya di folder komponen dinamis itu bila memang harus per request. Page induk tetap bisa statis atau memakai revalidasi normal.

FAQ

Apakah dynamic server usage selalu error?

Tidak. Ia menjadi error hanya ketika terjadi saat prerender halaman statis.

Kapan memakai dynamic = force-dynamic?

Pakai hanya pada segmen yang memang wajib membaca data per request, seperti halaman akun.

Apakah searchParams selalu membuat halaman dinamis?

Ya di Pages, tetapi di App Router ia hanya membuat batas yang memakainya menjadi dinamis bila diisolasi dengan Suspense.