eduardweb.
DeploymentIntermediar#seo#nextjs#react#metadata

Cum facem SEO dinamic în Next.js 16 fără să distrugem TTFB-ul

De Radu Grigore, 12 iun. 2026 · 19 vizualizări · 2 like-uri

Postat 12 iun. 2026
typescript
import { cache } from 'react'
import { notFound } from 'next/navigation'

// cache-uim fetch-ul ca să nu interogăm DB-ul de două ori
const getProduct = cache(async (id: string) => {
  const res = await fetch(`https://api.example.com/products/${id}`)
  if (!res.ok) return null
  return res.json()
})

export async function generateMetadata({ params }: { params: { id: string } }) {
  const product = await getProduct(params.id)
  if (!product) return {}

  return {
    title: `${product.title} | Shop-ul Nostru`,
    description: product.description,
    openGraph: {
      images: [{ url: product.image }],
    },
  }
}

La un proiect recent cu peste 12.000 de pagini de produs, SEO-ul era critic. Next.js a simplificat mult lucrurile cu noul Metadata API, dar dacă nu ești atent la detalii, riști să îți distrugi performanța serverului. Trecerea de la vechiul <Head> la generateMetadata vine cu câteva capcane de care m-am lovit direct.

Hai să vorbim pe șleau despre cum să configurezi asta corect, fără să dublezi timpul de răspuns al paginii.

Capcana ascunsă din generateMetadata: TTFB mărit

Cea mai mare greșeală pe care o văd în producție este interogarea bazei de date de două ori. O dată în generateMetadata pentru a lua titlul și descrierea produsului, și încă o dată în componenta principală a paginii pentru a randa conținutul.

Next.js ne spune că face deduplicare automată pentru fetch(). Sună bine pe hârtie. În realitate însă, dacă folosești un ORM (cum e Prisma sau Drizzle) sau un client nativ de bază de date, deduplicarea automată NU funcționează de la sine. Am pățit asta pe un magazin online unde TTFB-ul (Time to First Byte) sărise la peste 1.1 secunde doar din cauza interogărilor dublate.

Soluția este extrem de simplă, dar adesea ignorată: funcția cache din React. Înfășoară funcția de fetch în cache(), iar React se va asigura că baza de date este interogată o singură dată pe request.

OG Images dinamice: Satori vs servicii externe

Generarea de imagini Open Graph dinamice direct în Next.js folosind ImageResponse este excelentă, dar are un trade-off major. Satori (motorul de randare din spate) folosește un subset limitat de CSS. Dacă designerul tău a venit cu un layout complex, cu gradienți ciudați și umbre dubioase, te vei chinui ore întregi să le reproduci.

Pe de altă parte, generarea pe server consumă destul de mult CPU în medii serverless (cum ar fi Vercel sau Netlify). La un volum de 8.000 de vizite pe oră, am observat o creștere a costurilor pe serverless din cauza timpului de execuție pentru OG-uri. Sfatul meu: folosește caching agresiv la nivel de CDN pentru rutele de imagini dinamice. Setează headerele de Cache-Control corespunzător.

Structured Data (JSON-LD) curat

Pentru Google, JSON-LD este sfânt. Mulți încearcă să bage JSON-LD în obiectul returnat de generateMetadata. Deși tehnic poți pune taguri de script în alte moduri, cel mai curat mod în Next.js este să pui scriptul direct în componenta de pagină (Page).

Nu ai nevoie de librării externe complexe. Pur și simplu injectezi un tag <script> cu dangerouslySetInnerHTML. Google îl va citi perfect, iar codul tău rămâne simplu de întreținut. Ai grijă doar să sanitizezi orice date vin de la utilizatori ca să eviți vulnerabilitățile de tip XSS.

Next.js oferă instrumente excelente, dar optimizarea SEO nu se mai rezumă demult doar la a pune niște tag-uri în head. Trebuie să fim atenți la ce se întâmplă sub capotă cu request-urile noastre.

Voi cum gestionați generarea de OG-uri la proiectele mari? Rămâneți pe varianta nativă sau folosiți un serviciu extern precum Cloudinary?

Răspunsuri 0

Se încarcă răspunsurile…

Loghează-te pentru a răspunde

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