export default async function ProductPage({ params }: { params: { id: string } }) {
// Fetch cu tag pentru revalidare on-demand
const res = await fetch(`https://api.exemplu.ro/products/${params.id}`, {
next: {
tags: ['products', `product-${params.id}`],
revalidate: 3600 // ISR fallback la o oră
}
});
const product = await res.json();
return (
<main>
<h1>{product.name}</h1>
<p>Preț: {product.price} RON</p>
</main>
);
}M-am lovit de dilema asta pe aproape fiecare proiect de Next.js din ultimii ani. E ușor să zici „punem ISR la tot”, dar când te trezești că userul vede prețul vechi la checkout sau că build-ul durează 20 de minute, îți dai seama că ai calculat greșit.
În App Router, lucrurile s-au schimbat puțin față de vechiul getStaticProps, dar conceptele rămân aceleași. Am trecut printr-un proiect cu vreo 8k de pagini unde inițial am mers pe SSG pur. Eroare de începător: timpul de build a explodat și orice typo mic în footer însemna încă 15 minute de așteptat CI/CD-ul. Am economisit cam 30% la build time imediat ce am trecut pe o strategie hibridă.
SSG: Când conținutul e „rece”
SSG (Static Site Generation) e sfânt pentru paginile care nu se schimbă cu lunile. Pagina de „Termeni și Condiții”, „Despre noi” sau un Help Center. Am pățit la un moment dat să forțez ISR pe pagini statice de dragul de a fi „modern” și m-am trezit cu request-uri inutile către CMS la fiecare vizită a crawlerelor.
Trade-off: SSG e cel mai rapid pentru user, dar cel mai rigid pentru dev. Dacă ai peste 500 de pagini, gândește-te de două ori înainte să le faci pe toate pur statice la build time.
ISR: Compromisul de care avem nevoie
ISR (Incremental Static Regeneration) e bun când ai un blog sau un catalog de produse mare. Setezi un revalidate: 3600 și știi că într-o oră pagina se împrospătează.
Dar atenție la un aspect pe care mulți îl ignoră: ISR nu e „real-time” după ce trece ora aia. Primul user care intră după expirare tot vede varianta veche, în timp ce Next.js face revalidarea în spate. E ok pentru un blog tech, dar e groaznic pentru un site de știri unde „breaking news” trebuie să apară instant.
On-demand Revalidation: Regele în App Router
Aici e unde Next.js strălucește acum. Folosind revalidateTag sau revalidatePath, poți să ții paginile statice (deci ultra-rapide) până în secunda în care se schimbă ceva în baza de date. La un e-commerce cu 5000 de SKU-uri, am configurat un webhook în CMS care dă trigger la revalidare doar pe tag-ul produsului editat. Rezultatul? Cache hit rate de peste 90% și date mereu proaspete.
5 Cazuri reale și decizia luată
- Blog Personal / Portofoliu: SSG pur. Nu are rost să complici infrastructura pentru 10 pagini care se schimbă o dată la trei luni.
- Catalog Produse (E-commerce): ISR cu o fereastră mare (ex. 24h) + On-demand revalidation pe bază de webhook. Dacă se schimbă prețul în ERP, dăm flush la cache imediat.
- Dashboard User: Dynamic Rendering (SSR). Nu faci cache la date private. Am văzut implementări de ISR pe dashboard-uri și e un coșmar de securitate și logică dacă nu ești extrem de atent cu headerele de cache.
- Flash Sales / Stoc limitat: On-demand revalidation combinat cu un fetch client-side pentru stoc. Nu te baza pe cache-ul de server când ai 10 produse și 1000 de oameni care dau click.
- Site de știri / Publicație: ISR scurt (60 secunde). E suficient de rapid cât să nu pară site-ul „mort”, dar protejează baza de date de un spike de trafic neașteptat.
Cel mai mare trade-off la On-demand? Complexitatea. Trebuie să fii sigur că webhook-urile alea chiar ajung la destinație, altfel rămâi cu marfa veche pe „raft”. Tu ce strategie folosești cel mai des pentru paginile de produs?