eduardweb.
App RouterIntermediar#performance#nextjs#isr#caching#app-router

Next.js ISR vs SSG vs On-Demand: Cum alegi strategia de caching fără să distrugi serverul

De Cristian Barbu, 11 aug. 2026 · 7 vizualizări · 3 like-uri

Postat acum 6 zile
typescript
import { revalidateTag } from 'next/cache';
import { NextResponse, type NextRequest } from 'next/server';

// Route Handler pentru Webhook din CMS (ex: Strapi, Sanity, Shopify)
export async function POST(request: NextRequest) {
  const secret = request.headers.get('x-webhook-secret');
  
  if (secret !== process.env.CMS_WEBHOOK_SECRET) {
    return NextResponse.json({ message: 'Invalid token' }, { status: 401 });
  }

  const body = await request.json();
  const productId = body?.data?.id;

  if (!productId) {
    return NextResponse.json({ message: 'Missing product ID' }, { status: 400 });
  }

  // Invalidăm cache-ul strict pentru produsul modificat în CMS
  revalidateTag(`product-${productId}`);
  
  return NextResponse.json({ revalidated: true, now: Date.now() });
}

Am văzut prea multe proiecte de Next.js care dau crash la build pentru că încearcă să facă SSG la 50.000 de pagini sau care pun ISR la 5 secunde și dărâmă baza de date. În postarea asta trecem prin 5 cazuri reale din producție și îți arăt exact ce strategie să alegi ca să nu arunci banii pe infrastructură.

1. Marea confuzie: Timp vs. Evenimente

În App Router, caching-ul e activat implicit, dar trebuie să înțelegi ce faci. SSG înseamnă că paginile se generează o singură dată la build time. ISR pe timp (time-based) regenerează pagina în fundal după un interval definit, doar când un user o accesează. On-Demand Revalidation invalidează cache-ul instant când primești un eveniment (un webhook din CMS sau o acțiune de server).

Când alegi greșit, plătești scump. La un proiect cu 40k de produse, primul dev setase ISR pe timp la 30 de secunde pe tot catalogul. Boții de la Google accesau paginile continuu, iar baza de date Postgres stătea constant în 90% CPU de la atâtea query-uri de revalidare.

2. Cele 5 cazuri reale și ce soluție am ales

Cazul 1: Blogul companiei sau site-ul de prezentare (sub 100 pagini)

  • Soluție: SSG Pur (export const dynamic = 'force-static').
  • De ce: Totul se compilează la build. Build-ul durează sub 20 de secunde, iar paginile se servesc din Edge CDN cu latență de 15ms.

Cazul 2: E-commerce cu catalog mare (40.000+ produse)

  • Soluție: Hybrid — Partial SSG + On-Demand Revalidation.
  • Cum am făcut: Generăm static prin generateStaticParams doar cele mai vândute 500 de produse. Restul de 39.500 sunt randate la primul request. Când un admin schimbă prețul sau stocul, trimitem un webhook în API-ul de Next.js care apelează revalidateTag('product-123').
  • Rezultat: Am scăzut timpul de build de la 18 minute la doar 45 de secunde.

Cazul 3: Dashboard B2B / Portal de clienți

  • Soluție: Dynamic Rendering / SSR fără cache (export const revalidate = 0).
  • De ce: Datele sunt specifice fiecărui utilizator autentificat. Să încerci să faci caching la un dashboard financiar e garanția că un user va vedea datele altuia.

Cazul 4: Portal de știri cu trafic mare

  • Soluție: Time-based ISR (ex: 60 secunde) + On-Demand pentru Breaking News.
  • Trade-off: Merge brici pentru traficul masiv, dar ai un decalaj de maximum 1 minut la articole normale. Dacă apare o știre critică, redactorul apasă "Publish" în CMS și declanșează un revalidatePath('/stiri') ca să forțeze update-ul imediat.

Cazul 5: Pagina de căutare cu filtre complexe

  • Soluție: Client-side Fetching sau React Server Components dinamice pe URL searchParams.
  • De ce: Combinațiile de filtre sunt infinite. N-ai cum să faci cache eficient la /search?brand=nike&size=42&color=black&sort=asc.

3. Trade-off-uri sincere din producție

On-demand revalidation cu revalidateTag este soluția ideală pe hârtie, dar vine cu un cost de arhitectură: trebuie să fii extrem de disciplinat cu etichetarea datelor în fetch(). Dacă uiți să pui un tag pe o interogare sau dacă webhook-ul din CMS eșuează din cauza unui timeout, utilizatorii rămân cu date vechi pe site până la următorul deploy.

Pe de altă parte, ISR pe timp e simplu de configurat, dar e un "dumb cache". Va rula revalidarea chiar dacă datele din spate nu s-au schimbat deloc, consumând resurse de server aiurea.

Voi ce strategie folosiți pe proiectele mari de e-commerce în App Router? Ați trecut complet pe revalidateTag sau încă vă bazați pe revalidare cronologică?

Răspunsuri 0

Se încarcă răspunsurile…

Loghează-te pentru a răspunde

Doar membrii comunității pot lăsa comentarii.