Data lama di Server Component biasanya berasal dari fetch yang ter-cache. Tambahkan opsi revalidate yang tepat pada fetch bermasalah, bukan mematikan semua cache dengan no-store di semua tempat. Periksa dulu request mana yang stale, lalu pilih force-cache, next.revalidate, atau revalidateTag sesuai kebutuhan update datanya.
Kenapa Fetch di Server Component Next Js Malah Menyimpan Cache Lama
App Router menyimpan hasil fetch di server agar halaman statis bisa dirender ulang dengan cepat. Cache ini bertahan sampai durasi revalidate habis atau dihapus manual.
Masalah muncul ketika developer mengira setiap request mengambil data baru. Padahal tiga lapisan ini bekerja berbeda:
- Data Cache: menyimpan hasil fetch per URL dan opsi.
- Full Route Cache: menyimpan HTML hasil render route di server.
- Dynamic rendering: memaksa render ulang tiap request bila route memakai headers(), cookies(), atau searchParams.
Route yang membaca cookie auth otomatis menjadi dinamis. Route tanpa sinyal dinamis bisa tetap menyajikan HTML lama walau database sudah berubah.
Tabel Troubleshooting Fetch Cache yang Sering Stale
| Masalah | Penyebab | Solusi |
|---|---|---|
| List produk tidak update | Fetch memakai cache default | Tambah next: { revalidate: 60 } |
| Detail produk tertukar | URL fetch sama untuk ID beda | Sertakan ID di URL atau pakai tag unik |
| Data user lama setelah login | Full Route Cache dipakai ulang | Pakai cache: no-store khusus data user |
Cara Memperbaiki Fetch Cache Tanpa Mematikan Semua Cache
Ikuti urutan ini agar perbaikan tepat sasaran:
- Buka halaman bermasalah dan catat fetch mana yang menampilkan data lama.
- Cek apakah route memakai cookies(), headers(), atau searchParams.
- Tentukan durasi update. Data katalog cocok dengan revalidate, data transaksi cocok dengan no-store.
- Ubah opsi fetch sesuai kasusnya.
- Panggil revalidatePath atau revalidateTag dari Server Action setelah mutasi.
// Data katalog, update tiap 60 detik
const res = await fetch("https://api.example.com/products", {
next: { revalidate: 60 },
});
// Data sensitif per user, selalu baru
const user = await fetch("https://api.example.com/me", {
cache: "no-store",
});
// Data kategori dengan tag untuk invalidasi manual
const detail = await fetch("https://api.example.com/products/1", {
next: { tags: ["product-1"] },
});
Gunakan revalidatePath(“/products”) setelah mengubah banyak item. Gunakan revalidateTag(“product-1”) setelah mengubah satu produk saja agar invalidasi lebih hemat.
FAQ
Apakah semua fetch Server Component harus pakai no-store?
Tidak. Pakai no-store hanya untuk data per user atau data yang wajib baru tiap request.
Kapan memakai revalidate 60 dibanding revalidateTag?
Pakai revalidate: 60 untuk data yang boleh basi sebentar, pakai tag bila update harus langsung setelah mutasi.
Kenapa data masih lama setelah tambah revalidate?
Kemungkinan Full Route Cache belum diinvalidasi, panggil revalidatePath atau revalidateTag setelah perubahan data.