Nextjs Static Generation SSR ISR Dynamic Rendering
Definisi
Di Next.js App Router, halaman bisa dirender dengan beberapa strategi berbeda:
- Static Generation (SSG): HTML dibuat saat build, lalu dipakai ulang untuk banyak request.
- Server Side Rendering (SSR): HTML dibuat saat request masuk.
- Incremental Static Regeneration (ISR): halaman statis dibangun dulu, lalu diperbarui berkala atau on-demand tanpa rebuild penuh.
- Dynamic Rendering: halaman selalu dirender secara dinamis di server karena kontennya bergantung pada request, user, atau data yang harus fresh.
Keempat mode ini bukan label kosmetik. Mereka memengaruhi:
- kapan data diambil
- kapan HTML dibuat
- apa yang boleh di-cache
- seberapa cepat halaman pertama tampil
- seberapa mudah konten berubah di production
Kalau dipahami sebagai satu sistem, persoalannya bukan “pakai rendering apa?”, melainkan “konten ini boleh basi berapa lama, dan siapa yang menentukan hasilnya?”.
Kapan dipakai
Static Generation
Pakai SSG kalau konten relatif stabil dan aman dibangun di muka.
Cocok untuk:
- landing page marketing
- dokumentasi publik
- halaman about / help yang jarang berubah
- artikel blog yang tidak bergantung pada user
- halaman katalog yang isinya tidak berubah setiap request
SSG cocok saat kamu ingin:
- response sangat cepat
- beban server rendah
- cache alami dari CDN atau static hosting
- SEO yang stabil karena HTML sudah siap sejak awal
Server Side Rendering
Pakai SSR kalau HTML harus selalu dibentuk berdasarkan request terbaru.
Cocok untuk:
- dashboard personal
- halaman yang bergantung pada cookie atau session
- data yang sangat sensitif terhadap waktu
- halaman yang harus menyesuaikan header, locale, A/B flag, atau auth state
SSR cocok saat kamu butuh:
- data fresh per request
- variasi konten berdasarkan user
- keputusan yang tidak boleh ditunda ke cache lama
Konsekuensinya:
- setiap request membayar biaya render
- cache lebih sulit dipakai secara agresif
- latency sering lebih tinggi daripada SSG
Incremental Static Regeneration
Pakai ISR kalau kontennya statis sebagian besar waktu, tapi tetap harus bisa berubah tanpa rebuild penuh.
Cocok untuk:
- blog post yang kadang diedit
- katalog produk
- halaman listing yang update periodik
- halaman publik yang tidak perlu fresh per detik
- konten yang bisa toleran stale window singkat
ISR cocok saat kamu ingin:
- performa mirip static
- data tetap bisa berubah
- pembaruan terjadwal atau on-demand
Dynamic Rendering
Pakai dynamic rendering kalau hasil render benar-benar bergantung pada request runtime.
Cocok untuk:
- halaman yang membaca cookies, headers, atau session
- konten personalisasi
- halaman preview draft
- hasil pencarian atau filter yang perlu bereaksi ke request
- halaman yang memakai data yang harus selalu fresh dan tidak aman di-cache
Dynamic rendering adalah pilihan default secara praktis ketika App Router melihat sinyal bahwa halaman tidak aman diperlakukan statis.
Cara kerja strategi render di App Router
App Router tidak memilih strategi hanya dari nama file. Ia menyimpulkan strategi dari kombinasi:
- penggunaan
fetch()dan opsi caching-nya - penggunaan Dynamic APIs seperti
cookies(),headers(), atausearchParamstertentu - konfigurasi segment seperti
dynamic,revalidate, danfetchCache - keberadaan
generateStaticParams()untuk route dinamis - apakah route perlu membaca data yang hanya tersedia saat request
Artinya, satu page bisa terlihat statis di local, tapi berubah menjadi dinamis di production karena ada satu dependency yang memaksa request-time render.
Aturan besar yang perlu diingat
- Kalau semua data bisa diketahui saat build dan tidak ada Dynamic API, halaman cenderung statis.
- Kalau ada data yang diberi waktu revalidate, halaman masih bisa statis tetapi punya refresh window.
- Kalau ada
cookies(),headers(),no-store, atau konfigurasi eksplisit dinamis, halaman cenderung SSR / dynamic. - Route dinamis tanpa
generateStaticParams()tidak otomatis statis.
Diagram keputusan render strategy
Static Generation (SSG)
SSG membangun HTML saat build. Hasilnya disimpan sebagai output yang bisa disajikan cepat tanpa menjalankan render penuh untuk setiap request.
Karakter utama
- HTML siap lebih awal
- request user hanya mengambil hasil yang sudah jadi
- sangat cocok untuk cache CDN
- biaya server per request rendah
Di App Router
SSG biasanya muncul kalau:
- page tidak memakai Dynamic API
- data fetch bisa diselesaikan saat build
- route dinamis memiliki
generateStaticParams() - tidak ada konfigurasi yang memaksa render runtime
Contoh kasar:
export default async function Page() {
const posts = await fetch('https://example.com/api/posts').then((res) => res.json())
return <pre>{JSON.stringify(posts, null, 2)}</pre>
}Kalau data ini aman dibangun saat build dan tidak dipaksa refresh per request, output-nya bisa statis.
Kelebihan
- sangat cepat saat request
- murah di server
- stabil untuk SEO dan preview
- mudah dicache
Kekurangan
- konten bisa basi sampai build berikutnya
- perubahan konten butuh mekanisme refresh
- tidak cocok untuk data yang personal atau sangat dinamis
Server Side Rendering (SSR)
SSR merender HTML saat request datang. Hasilnya bisa bergantung pada keadaan request saat itu juga.
Karakter utama
- render terjadi per request
- HTML bisa berbeda antar user atau antar request
- cocok untuk data yang tidak boleh stale
- lebih mahal daripada static
Di App Router
SSR biasanya muncul kalau halaman:
- memakai
cookies()atauheaders()untuk menentukan isi - memakai
cache: 'no-store' - diberi
export const dynamic = 'force-dynamic' - bergantung pada informasi request yang tidak diketahui saat build
Contoh pola:
import { cookies } from 'next/headers'
export default async function Page() {
const session = cookies().get('session')
const me = await fetch('https://example.com/api/me', {
cache: 'no-store',
}).then((res) => res.json())
return <pre>{JSON.stringify({ session: Boolean(session), me }, null, 2)}</pre>
}Kelebihan
- selalu fresh
- bagus untuk personalisasi
- cocok untuk auth-sensitive UI
Kekurangan
- render per request menambah latensi
- cache lebih sulit dioptimalkan
- beban server lebih tinggi
Incremental Static Regeneration (ISR)
ISR berada di tengah. HTML tetap statis, tetapi Next.js diberi izin memperbarui hasil itu setelah waktu tertentu atau setelah event tertentu.
Karakter utama
- terasa seperti static saat request normal
- bisa direfresh tanpa rebuild penuh
- cocok untuk konten publik yang berubah sesekali
- bisa menjaga cache tetap berguna sambil mengurangi stale content
Bentuk umum
export const revalidate = 60
export default async function Page() {
const posts = await fetch('https://example.com/api/posts', {
next: { revalidate: 60 },
}).then((res) => res.json())
return <pre>{JSON.stringify(posts, null, 2)}</pre>
}Maknanya:
- output bisa dipakai ulang selama window yang ditentukan
- setelah itu Next.js boleh mengambil data baru
- halaman tetap punya karakter statis, bukan render ulang penuh setiap request
Kapan ISR unggul
ISR biasanya paling enak untuk:
- artikel yang editnya tidak tiap menit
- halaman katalog
- dokumentasi produk
- landing page yang copy-nya bisa berubah beberapa kali sehari
Kelebihan
- performa dekat static
- konten bisa diperbarui tanpa rebuild total
- cache tetap membantu
Kekurangan
- ada stale window
- perubahan tidak selalu langsung terlihat
- kalau invalidasi salah, konten bisa lama tertahan
Dynamic Rendering
Dynamic rendering di App Router berarti halaman diputuskan untuk dirender runtime karena tidak aman atau tidak mungkin diperlakukan statis.
Pemicu umum
cookies()headers()cache: 'no-store'dynamic = 'force-dynamic'- data request-specific
- autentikasi dan personalisasi yang memengaruhi HTML
Kapan ini bukan pilihan terakhir
Dynamic rendering bukan berarti buruk. Kadang itu justru pilihan yang benar. Yang perlu dijaga adalah kesadaran bahwa biaya runtime-nya nyata.
Gunakan kalau:
- HTML memang harus berbeda per request
- hasil statis akan berisiko salah
- cache agresif justru merusak correctness
Bagaimana App Router memilih strategi
Urutan mental yang berguna:
- Apakah halaman butuh state request-time?
- Jika ya, cenderung dynamic / SSR.
- Apakah data bisa dicache dan direvalidate?
- Jika ya, bisa statis dengan ISR.
- Apakah semua data bisa diketahui saat build?
- Jika ya, bisa SSG.
- Apakah route dinamis punya daftar params build-time?
- Jika ya, bisa pre-render sebagian atau seluruhnya.
- Apakah ada konfigurasi eksplisit yang memaksa salah satu mode?
dynamic,revalidate,fetchCache,no-storebisa mengubah hasil akhir.
Tabel keputusan singkat
| Kondisi | Strategi yang cenderung dipilih |
|---|---|
| Konten tetap, tidak ada Dynamic API | SSG |
| Konten tetap tapi boleh refresh berkala | ISR |
| Konten bergantung cookie/header/session | SSR / dynamic |
| Data harus selalu fresh | SSR / dynamic |
| Route dinamis punya params saat build | SSG parsial / penuh |
Jebakan umum saat konten berubah di production
1. Mengira sudah update, padahal masih kena cache
Ini yang paling sering.
Gejalanya:
- local terlihat benar
- production masih menampilkan konten lama
- deploy sukses, tapi halaman belum berubah
Penyebab umum:
- route statis masih disajikan dari cache
- ISR belum melewati window refresh
- revalidation belum kena path yang benar
- CDN masih menyimpan versi lama
2. generateMetadata atau page fetch tidak selaras
Kalau metadata berubah tapi isi halaman belum, atau sebaliknya, crawler dan user bisa melihat sinyal yang berbeda.
Jangan biarkan:
- title di head sudah baru
- isi halaman masih versi lama
3. Pakai cache: 'force-cache' tanpa sadar
Ini bisa membuat data terasa “stabil” padahal justru menahan perubahan terlalu lama.
4. Salah memilih scope revalidate
Terlalu sempit:
- halaman daftar berubah, detail tidak ikut berubah
Terlalu luas:
- semua halaman ikut re-render atau re-fetch tanpa perlu
5. Route dinamis diperlakukan seolah statis
Kalau route [slug] atau [id] tidak punya generateStaticParams(), asumsi build-time bisa meleset.
Gejalanya:
- halaman tertentu 404 di production
- halaman baru tidak muncul setelah konten baru ditambahkan
- build berhasil, runtime gagal melayani slug baru
6. Menggunakan Dynamic API tanpa sadar
Satu pemanggilan cookies() atau headers() bisa mengubah strategi render.
Sering terjadi saat:
- menambahkan auth gating kecil
- membaca locale dari header
- memeriksa preview flag
- membaca A/B test cookie
7. ISR tapi konten butuh update instan
ISR punya stale window. Kalau bisnis butuh perubahan langsung, ISR saja tidak cukup.
Contoh:
- status stok
- harga yang berubah cepat
- dashboard operasional
8. Preview mode tertukar dengan cache publik
Konten draft atau preview sering memerlukan jalur render yang berbeda. Kalau cache publik ikut dipakai, editor bisa melihat versi lama.
9. Serverless / edge / CDN menambah lapisan cache
Production sering punya lebih dari satu cache:
- Next.js cache
- platform cache
- CDN cache
- browser cache
Masalah sering muncul karena kita hanya mengecek satu lapisan.
Praktik debug yang berguna
Kalau konten berubah tapi hasil tidak ikut berubah, cek urutan ini:
- Apakah route ini static, ISR, atau dynamic?
- Apakah ada
cookies(),headers(), atauno-store? - Apakah
revalidatesudah diset di level yang benar? - Apakah revalidation path/tag kena route yang benar?
- Apakah CDN masih menyimpan response lama?
- Apakah metadata dan page content membaca sumber data yang sama?
Tanda-tanda umum
- stale konsisten → cache / ISR / revalidation salah
- berbeda per user → cookies / headers / auth memaksa dynamic
- baru setelah hard refresh → browser atau CDN cache ikut bermain
- lokal benar, production salah → strategi render atau cache layer berbeda
Contoh pola yang sehat
Konten publik yang jarang berubah
- SSG atau ISR
- cache agresif
- refresh lewat revalidate
Dashboard pribadi
- SSR / dynamic
- cache dibatasi
- data dibaca sesuai session
Halaman produk
- static + ISR
- on-demand revalidation setelah admin update
- route detail dan listing direvalidate bersama
Ringkasan keputusan
Pilih mode seperti ini:
- SSG kalau konten stabil dan aman dibangun di muka.
- SSR kalau HTML harus mengikuti request terbaru.
- ISR kalau konten dominan statis tapi perlu refresh berkala atau on-demand.
- Dynamic rendering kalau hasilnya bergantung pada request runtime atau data yang tidak boleh basi.
Aturan praktis paling penting:
- makin banyak request-time dependency, makin besar peluang halaman jadi dynamic
- makin besar toleransi stale, makin cocok static atau ISR
- makin sensitif data terhadap user atau waktu, makin masuk akal SSR / dynamic
Referensi terkait
- Next.js App Router rendering behavior
revalidatedan cache control di Server ComponentsgenerateStaticParams()untuk route dinamiscookies()danheaders()sebagai pemicu dynamic rendering- produksi cache: Next.js cache, CDN cache, browser cache