eduardweb.
DeploymentIntermediar#performance#seo#nextjs#web-dev

Cum să nu-ți distrugi TTFB-ul cu generateMetadata în Next.js 16

De Andreea Crăciun, 4 iun. 2026 · 2 vizualizări · 3 like-uri

Postat acum 5 zile
typescript
import { cache } from 'react';
import { Metadata } from 'next';

const getProduct = cache(async (id: string) => {
  // Deduplicăm manual interogarea în baza de date
  return await db.product.findUnique({ where: { id } });
});

interface Props {
  params: { id: string };
}

export async function generateMetadata({ params }: Props): Promise<Metadata> {
  const product = await getProduct(params.id);
  if (!product) return {};

  return {
    title: product.name,
    description: product.description,
    openGraph: {
      images: [{ url: `/api/og?title=${encodeURIComponent(product.name)}` }],
    },
  };
}

export default async function Page({ params }: Props) {
  const product = await getProduct(params.id);
  if (!product) return null;

  const jsonLd = {
    '@context': 'https://schema.org',
    '@type': 'Product',
    name: product.name,
    description: product.description,
  };

  return (
    <main>
      <script
        type="application/ld+json"
        dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
      />
      <h1>{product.name}</h1>
    </main>
  );
}

Salutare! Hai să vorbim direct despre Metadata API în Next.js, că tot văd oameni care se încurcă în configurări când vine vorba de SEO dinamic. Am implementat recent fluxul ăsta pe un shop cu peste 12.000 de produse și am scos câteva învățăminte care vă pot salva de la un TTFB dezastruos. Dacă vrei indexare perfectă în Google și social media share-uri care arată impecabil, trebuie să înțelegi cum colaborează serverul cu clientul în noul App Router.

Capcana ascunsă din generateMetadata și TTFB-ul

Cea mai mare greșeală pe care o văd în producție este duplicarea apelurilor către baza de date. Next.js rulează generateMetadata pe server înainte de a începe să trimită HTML-ul către client. Dacă în funcția asta faci un apel la API să iei datele produsului, iar apoi în pagina propriu-zisă (care e tot Server Component) faci exact același apel, ai dublat latența.

La proiectul de care vă ziceam, ne trezisem cu un TTFB de aproape 1.1 secunde pe paginile de produs. Soluția? Next.js face deduplicare automată pentru funcția nativă fetch(). Dar dacă folosești un ORM ca Prisma sau Drizzle, sau un client de Postgres direct, deduplicarea nu se întâmplă de la sine. Trebuie să folosești funcția cache din React pentru a memora rezultatul interogării pe durata aceluiași request. E o linie de cod simplă care ne-a scăzut încărcarea pe baza de date la jumătate.

Imagini OpenGraph (OG) dinamice: Vercel OG sau CDN extern?

Generarea dinamică de imagini folosind @vercel/og (cu ImageResponse) este extrem de elegantă pentru că scrii layout-ul în JSX și CSS. Totuși, trade-off-ul este unul financiar și de performanță. Rularea de funcții Edge sau Serverless pentru fiecare share de link poate deveni costisitoare pe Vercel dacă ai trafic masiv sau dacă boții de la Google și Facebook îți scanează intens site-ul.

Pentru site-uri medii, funcționează excelent direct în Next.js. Dar dacă ai zeci de mii de pagini accesate constant de crawlere, recomandarea mea sinceră este să folosești un CDN extern (cum e Cloudinary) unde generezi imaginea printr-un URL cu parametri, sau să configurezi reguli de cache extrem de agresive (de exemplu, stale-while-revalidate pe câteva săptămâni) ca să nu rulezi codul de generare la fiecare request. Noi am ales varianta cu CDN dedicat pentru produsele foarte vechi și generare dinamică doar pentru ofertele de campanie care se schimbă zilnic.

Structured Data (JSON-LD) fără bătăi de cap

Nu încercați să înghesuiți JSON-LD-ul în obiectul returnat de generateMetadata. API-ul de metadata din Next.js nu e gândit pentru structuri complexe de tip schemă, chiar dacă teoretic ai putea să trântești niște taguri custom acolo. Cel mai curat mod de a adăuga date structurate este să injectezi un script direct în corpul paginii tale (Server Component).

Next.js este destul de deștept încât să facă hoisting la acest tag în head-ul paginii în mod automat dacă îl pui în componentă. În plus, codul rămâne mult mai lizibil și poți folosi tipurile de la schema-dts ca să fii sigur că nu trimiți date invalide către Google Search Console. Am observat că de când am trecut la structura asta curată, erorile de parsare în Search Console au scăzut la zero.

Voi cum gestionați imaginile OG în proiectele mari? Rămâneți pe varianta nativă din Next.js sau preferați să le generați extern pentru a descărca serverul de Node?

Răspunsuri 0

Se încarcă răspunsurile…

Loghează-te pentru a răspunde

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