Design wechseln

Next.js Core Web Vitals in der Praxis: LCP, FCP und CLS im Griff

Easton editorial illustration: state-management shelf

Letzten Monat habe ich die Performance-Optimierung eines E-Commerce-Projekts übernommen. Der Lighthouse-Score blieb bei etwa 65 Punkten, LCP (Largest Contentful Paint) schwankte um 3,5 Sekunden. Der Auftraggeber berichtete von hoher Absprungrate und stagnierender Conversion-Rate.

Zwei Wochen systematischer Core Web Vitals-Optimierung brachten den Lighthouse-Score auf 95 Punkte und senkten LCP auf 1,2 Sekunden. Noch wichtiger: Die Conversion-Rate stieg um 28 %. Performance-Optimierung ist nicht nur eine technische Kennzahl – sie schafft echten Geschäftswert.

Laut aktuellen Daten aus 2025 erfüllen nur 47 % der Websites Googles Core Web Vitals-Standards. Schlechte Performance kostet 8–35 % Umsatz, Ranking und Conversions. Das ist keine Panikmache, sondern die realen wirtschaftlichen Folgen.

In diesem Artikel teile ich Praxiserfahrungen aus der Next.js-Performance-Optimierung. Sie lernen:

  • Konkrete Optimierungsmethoden für die drei Kernkennzahlen LCP, INP und CLS
  • 10+ direkt kopierbare Codebeispiele
  • 5 typische Performance-Fallstricke
95 Punkte
Lighthouse nach Optimierung
Von 65 Punkten gestiegen
1,2 s
LCP nach Optimierung
Von 3,5 s gesenkt
28%
Conversion-Steigerung
Geschäftswert durch Performance
47%
Anteil konformer Websites
Core Web Vitals-Daten 2025
Source: Praxisdaten

Core Web Vitals 2025 – was sich geändert hat

Bevor Sie optimieren, sollten Sie die aktuellen Regeln kennen. Viele Artikel sprechen noch von FID (First Input Delay) – dieser Wert wurde jedoch im März 2024 abgeschafft.

Die drei aktuellen Kernkennzahlen

Google konzentriert sich jetzt auf diese drei Metriken:

  1. LCP (Largest Contentful Paint) – Largest Contentful Paint

    • Ziel: ≤ 2,5 s
    • Misst die Ladeperformance
    • Trägt 25 % zum Lighthouse-Score bei
  2. INP (Interaction to Next Paint) – Interaction to Next Paint

    • Ziel: ≤ 200 ms
    • Misst die Reaktionsgeschwindigkeit bei Interaktionen
    • Seit März 2024 Ersatz für FID
  3. CLS (Cumulative Layout Shift) – Cumulative Layout Shift

    • Ziel: < 0,1
    • Misst visuelle Stabilität

FCP (First Contentful Paint) ist keine Kernkennzahl mehr, bleibt aber wichtig – er prägt den ersten Eindruck.

Warum diese Kennzahlen wichtig sind

Kennen Sie das? Sie öffnen eine Website, wollen auf einen Button klicken – und plötzlich springt die Seite, Sie treffen woanders. Das ist schlechtes CLS.

Oder Sie starren auf einen weißen Bildschirm und denken: „Ist die Verbindung abgebrochen?” Das ist zu langsames LCP.

Laut Chrome-Team liegt der durchschnittliche LCP-Wert top-performanter Websites bei etwa 1.220 ms. Liegt Ihr LCP über 2,5 Sekunden, hängen Sie hinter den meisten Wettbewerbern zurück.

LCP-Optimierung – das größte Inhaltselement schnell anzeigen

LCP war die Kennzahl, in die ich am meisten Zeit investiert habe – und der Effekt war am deutlichsten. Im Folgenden Schritt für Schritt.

Schritt 1: Ihr LCP-Element identifizieren

Vor der Optimierung müssen Sie wissen, welches Element LCP ist. Typischerweise:

  • Hero-Bild im Above-the-Fold-Bereich
  • Video-Poster
  • Große Überschrift oder Textblock

Schnelle Methode:

  1. Chrome DevTools öffnen (F12)
  2. Ctrl+Shift+P drücken (Mac: Cmd+Shift+P)
  3. „Show Rendering” eingeben
  4. „Core Web Vitals” aktivieren
  5. Seite neu laden – oben rechts erscheint das LCP-Element

Beim E-Commerce-Projekt war das LCP-Element das Hero-Bild auf der Startseite – ein 2 MB großes JPG. Das war das Problem.

Bildoptimierung: next/image richtig einsetzen

Viele glauben, mit der Next.js Image-Komponente sei alles erledigt. Das stimmt nicht – ich dachte anfangs genauso, LCP blieb trotzdem langsam.

Priorität ist entscheidend

Für LCP-Bilder müssen Sie dem Browser signalisieren: „Dieses Bild ist wichtig, bitte zuerst laden!” Next.js bietet zwei Wege:

Next.js 13–15 (weit verbreitet):

import Image from 'next/image';

export default function Hero() {
  return (
    <Image
      src="/hero-image.jpg"
      width={1200}
      height={630}
      priority  // Wichtig: Browser soll zuerst laden
      fetchPriority="high"  // Zusätzliche Absicherung
      alt="Produkt-Hero"
    />
  );
}

Next.js 16+ (neueste Version):

Next.js 16 hat priority abgeschafft und nutzt stattdessen:

<Image
  src="/hero-image.jpg"
  width={1200}
  height={630}
  loading="eager"  // Sofort laden, kein Lazy Loading
  fetchPriority="high"  // Hohe Priorität
  alt="Produkt-Hero"
/>

Warum zwei Attribute? priority fügt automatisch Preload-Tags hinzu, fetchPriority signalisiert die Wichtigkeit der Ressource. Beides zusammen wirkt am besten.

Typische Fehler im Vergleich:

// ❌ Falsch: wird lazy geladen, LCP langsam
<Image
  src="/hero-image.jpg"
  width={1200}
  height={630}
  alt="Produkt-Hero"
/>

// ❌ Falsch: keine Größenangabe
<Image
  src="/hero-image.jpg"
  priority
  alt="Produkt-Hero"
/>

Warum Größenangaben wichtig sind

Die Next.js Image-Komponente verlangt width und height – nicht aus Schik, sondern um CLS (Layout-Verschiebungen) zu vermeiden.

Bei responsivem Layout:

// Mit fill für responsives Layout
<div style={{ position: 'relative', width: '100%', aspectRatio: '16/9' }}>
  <Image
    src="/hero-image.jpg"
    fill
    priority
    style={{ objectFit: 'cover' }}
    alt="Produkt-Hero"
  />
</div>

Der Eltern-Container braucht eine feste Größe oder aspect-ratio, sonst weiß das Bild nicht, wie groß es rendern soll.

Font-Optimierung: next/font mit automatischem Inline

Langsame Font-Ladezeiten bremsen LCP – besonders bei großen Schriftdateien. Next.js 13 führte next/font ein.

Google Fonts:

// app/layout.jsx
import { Inter, Noto_Sans_SC } from 'next/font/google';

const inter = Inter({
  subsets: ['latin'],
  display: 'swap',  // Font-Flackern vermeiden
});

const notoSansSC = Noto_Sans_SC({
  subsets: ['chinese-simplified'],
  weight: ['400', '700'],
  display: 'swap',
});

export default function RootLayout({ children }) {
  return (
    <html lang="zh-CN" className={`${inter.className} ${notoSansSC.className}`}>
      <body>{children}</body>
    </html>
  );
}

Eigene Fonts:

import localFont from 'next/font/local';

const myFont = localFont({
  src: './my-font.woff2',
  display: 'swap',
});

export default function Layout({ children }) {
  return <div className={myFont.className}>{children}</div>;
}

next/font übernimmt automatisch:

  • Font-CSS inline einbinden, weniger Netzwerk-Requests
  • Subsetting – nur benötigte Zeichen laden
  • Font-Dateien vorladen
  • Layout-Verschiebungen eliminieren

Nach dem Wechsel zu next/font sank LCP im Projekt um weitere 0,3 Sekunden.

Server-Antwortzeit reduzieren

Bilder und Fonts optimiert, LCP immer noch langsam? Dann liegt es oft an der Server-Antwortzeit (TTFB).

Statische Generierung bevorzugen

Next.js bietet mehrere Rendering-Modi – Performance von gut nach schlecht:

  1. SSG (Static Site Generation) – HTML beim Build, am schnellsten
  2. ISR (Incremental Static Regeneration) – statische Seiten bei Bedarf neu generieren
  3. SSR (Server-Side Rendering) – HTML pro Request, langsamer
  4. CSR (Client-Side Rendering) – Client-Rendering, LCP am langsamsten

SSG nutzen, wo möglich:

// app/blog/[slug]/page.jsx
export async function generateStaticParams() {
  const posts = await getPosts();
  return posts.map((post) => ({
    slug: post.slug,
  }));
}

export default async function BlogPost({ params }) {
  const post = await getPost(params.slug);
  return <article>{/* ... */}</article>;
}

Bei Echtzeit-Daten ISR nutzen:

// app/products/[id]/page.jsx
export const revalidate = 3600; // Stündlich neu generieren

export default async function ProductPage({ params }) {
  const product = await getProduct(params.id);
  return <div>{/* ... */}</div>;
}

CDN und Edge Network

Bei Vercel-Deployment werden statische Assets automatisch global über das Edge Network ausgeliefert – TTFB sinkt deutlich.

Auf anderen Plattformen Cloudflare, AWS CloudFront o. Ä. als CDN einsetzen.

Schwere Berechnungen nicht im Server-Request

Den Fehler habe ich selbst gemacht: komplexe Datenverarbeitung im Server-Request, 500 ms pro Render – LCP leidet.

Anti-Beispiel:

// ❌ Falsch: Berechnung bei jedem Request
export default async function Page() {
  const data = await fetchData();
  const processed = heavyProcessing(data); // 500 ms
  return <div>{processed}</div>;
}

Richtig:

Ergebnisse cachen oder beim Build vorberechnen:

// ✅ Richtig: beim Build berechnen
export async function generateStaticParams() {
  const data = await fetchData();
  const processed = heavyProcessing(data);
  // Ergebnis in DB oder Datei speichern
  await saveProcessedData(processed);
}

export default async function Page() {
  const processed = await getProcessedData(); // direkt lesen
  return <div>{processed}</div>;
}

CLS-Optimierung – Layout-Sprünge beseitigen

CLS (Cumulative Layout Shift) ist oft am frustrierendsten – die Seite springt plötzlich. Das Problem hat mich eine Weile beschäftigt.

Größen für Bilder und Medien reservieren

Häufigste CLS-Ursache: Bilder laden und verschieben das Layout. Lösung: Größe vorab angeben.

Next.js Image erledigt das automatisch:

// ✅ Richtig: width/height gesetzt, kein CLS
<Image
  src="/product.jpg"
  width={400}
  height={300}
  alt="Produktbild"
/>

Dynamische Bilder aus dem CMS?

// ✅ Richtig: aspect-ratio reserviert Platz
<div style={{ position: 'relative', width: '100%', aspectRatio: '4/3' }}>
  <Image
    src={dynamicImageUrl}
    fill
    style={{ objectFit: 'cover' }}
    alt="Dynamisches Bild"
  />
</div>

Videos ebenso:

<video
  width="1280"
  height="720"
  poster="/video-poster.jpg"
  controls
>
  <source src="/video.mp4" type="video/mp4" />
</video>

Platz für dynamische Inhalte reservieren

Werbung, Banner, Embeds (z. B. Twitter-Karten) verursachen CLS. Platz im Voraus reservieren.

Werbe-Container:

// ✅ Richtig: Werbehöhe reserviert
<div
  style={{
    minHeight: '250px',  // Standardhöhe Google AdSense
    backgroundColor: '#f0f0f0'  // Platzhalter-Hintergrund
  }}
>
  {/* Werbe-Skript */}
  <ins className="adsbygoogle" />
</div>

Benachrichtigungsleiste:

// ❌ Falsch: plötzliches Erscheinen, Seite rutscht nach unten
{showBanner && <NotificationBanner />}

// ✅ Richtig: Platz von Anfang an reserviert
<div style={{ minHeight: '60px' }}>
  {showBanner ? <NotificationBanner /> : <div style={{ height: '60px' }} />}
</div>

Skeleton-Screens:

Für dynamisch geladene Inhalte Skeleton-Platzhalter nutzen:

function ProductList() {
  const { data, isLoading } = useQuery('products', fetchProducts);

  if (isLoading) {
    return (
      <div className="grid grid-cols-3 gap-4">
        {Array.from({ length: 6 }).map((_, i) => (
          <div key={i} className="skeleton" style={{ height: '300px' }} />
        ))}
      </div>
    );
  }

  return (
    <div className="grid grid-cols-3 gap-4">
      {data.map(product => <ProductCard key={product.id} {...product} />)}
    </div>
  );
}

Font-Lade-Optimierung

Fonts verursachen CLS – sichtbar als Text-Flackern oder Größenwechsel.

next/font löst das automatisch; manuell geht es so:

const inter = Inter({
  subsets: ['latin'],
  display: 'optional',  // Wenn Font nicht rechtzeitig da: Systemfont nutzen
  adjustFontFallback: true,  // Fallback-Größe anpassen, weniger Sprung
});

Optionen für display:

  • swap: Fallback zuerst, dann Wechsel (kann CLS verursachen)
  • optional: Font nicht rechtzeitig geladen → Systemfont (empfohlen)
  • block: Text kurz ausblenden (nicht empfohlen)
  • fallback: Kompromiss zwischen swap und optional

Ich empfehle optional – eventuell ohne Custom-Font, dafür stabilere UX.

JavaScript-gesteuertes responsives Layout vermeiden

Der häufigste CLS-Fallstrick 2025! Viele Next.js-Projekte machen denselben Fehler.

Typischer Fehlercode:

// ❌ Falsch: verursacht starkes CLS
import { useMediaQuery } from '@/hooks/useMediaQuery';

export default function ResponsiveLayout() {
  const isMobile = useMediaQuery('(max-width: 768px)');

  return (
    <div>
      {isMobile ? (
        <MobileNav />
      ) : (
        <DesktopNav />
      )}
    </div>
  );
}

Warum CLS?

  1. Beim ersten Render ist JavaScript noch nicht gelaufen – isMobile ist undefined oder Default
  2. Nach JS-Ausführung liefert useMediaQuery den echten Wert
  3. Re-Render, Layout springt

Bei SSR noch schlimmer – der Server kennt die Bildschirmbreite nicht.

Richtig: CSS Media Queries

// ✅ Richtig: CSS steuert Sichtbarkeit, kein CLS
export default function ResponsiveLayout() {
  return (
    <>
      <nav className="mobile-nav md:hidden">
        <MobileNav />
      </nav>
      <nav className="desktop-nav hidden md:block">
        <DesktopNav />
      </nav>
    </>
  );
}

Oder mit CSS-in-JS:

export default function ResponsiveLayout() {
  return (
    <div className="responsive-container">
      <MobileNav />
      <DesktopNav />
      <style jsx>{`
        .responsive-container > :global(.mobile-nav) {
          display: block;
        }
        .responsive-container > :global(.desktop-nav) {
          display: none;
        }
        @media (min-width: 768px) {
          .responsive-container > :global(.mobile-nav) {
            display: none;
          }
          .responsive-container > :global(.desktop-nav) {
            display: block;
          }
        }
      `}</style>
    </div>
  );
}

Brauchen Sie JavaScript für unterschiedliche Daten (nicht nur Layout), User-Agent serverseitig auswerten:

// app/page.jsx
import { headers } from 'next/headers';

export default async function Page() {
  const headersList = headers();
  const userAgent = headersList.get('user-agent') || '';
  const isMobile = /mobile/i.test(userAgent);

  return (
    <div>
      {isMobile ? <MobileView /> : <DesktopView />}
    </div>
  );
}

Server und Client rendern identisch – kein CLS.

FCP-Optimierung – First Contentful Paint beschleunigen

FCP ist keine Kernkennzahl, prägt aber den ersten Eindruck. Lange weiße Bildschirme → Nutzer schließen die Seite.

Kritische Ressourcen optimieren

Langsames FCP entsteht oft durch render-blockierende Ressourcen. Chrome DevTools Coverage zeigt ungenutztes CSS und JavaScript.

Kritisches CSS inline:

Next.js optimiert CSS automatisch; manuell geht es so:

// app/layout.jsx
export default function RootLayout({ children }) {
  return (
    <html>
      <head>
        <style
          dangerouslySetInnerHTML={{
            __html: `
              /* Kritisches CSS: Above-the-Fold */
              body { margin: 0; font-family: system-ui; }
              .hero { height: 100vh; }
            `,
          }}
        />
      </head>
      <body>{children}</body>
    </html>
  );
}

Nicht-kritisches CSS verzögert laden:

Styles für Modals, Accordions etc. können später geladen werden:

// CSS dynamisch in Komponente importieren
import dynamic from 'next/dynamic';

const Modal = dynamic(() => import('./Modal'), {
  loading: () => <p>Loading...</p>,
});

Drittanbieter-Skripte steuern

Google Analytics, Werbung, Social Plugins – Performance-Killer. Viele langsame FCP-Werte kommen daher.

next/script nutzen:

Next.js bietet die Script-Komponente mit Lade-Strategien:

import Script from 'next/script';

export default function Layout({ children }) {
  return (
    <>
      {children}

      {/* Google Analytics: nach Interaktivität laden */}
      <Script
        src="https://www.googletagmanager.com/gtag/js?id=GA_MEASUREMENT_ID"
        strategy="lazyOnload"
      />
      <Script id="ga-init" strategy="lazyOnload">
        {`
          window.dataLayer = window.dataLayer || [];
          function gtag(){dataLayer.push(arguments);}
          gtag('js', new Date());
          gtag('config', 'GA_MEASUREMENT_ID');
        `}
      </Script>

      {/* Facebook Pixel: verzögert laden */}
      <Script
        src="https://connect.facebook.net/en_US/fbevents.js"
        strategy="lazyOnload"
      />
    </>
  );
}

strategy-Optionen:

  • beforeInteractive: vor Interaktivität (kritische Skripte)
  • afterInteractive: nach Interaktivität (Standard)
  • lazyOnload: bei Idle (Analytics und Werbung)
  • worker: im Web Worker (experimentell)

Alle nicht essentiellen Drittanbieter-Skripte auf lazyOnload umgestellt – FCP um 0,8 Sekunden verbessert.

Code-Splitting und Lazy Loading

Next.js splittet automatisch; manchmal braucht es manuelle Optimierung.

Komponenten lazy laden:

import dynamic from 'next/dynamic';

// Kommentare lazy laden
const Comments = dynamic(() => import('./Comments'), {
  loading: () => <div>Kommentare werden geladen...</div>,
  ssr: false,  // kein SSR
});

export default function BlogPost({ post }) {
  return (
    <article>
      <h1>{post.title}</h1>
      <div>{post.content}</div>
      {/* Kommentare erst beim Scrollen laden */}
      <Comments postId={post.id} />
    </article>
  );
}

Große Bibliotheken lazy laden:

Chart.js, Rich-Text-Editoren etc. nur bei Bedarf laden.

Beispiel: Chart.js – 800 KB sparen

Ein Projekt importierte Chart.js global, nutzte es aber nur auf dem Dashboard – jede Seite lud 800 KB.

Vorher:

// ❌ Falsch: globaler Import, jede Seite lädt mit
import { Chart } from 'chart.js';

export default function Dashboard() {
  return <canvas ref={chartRef} />;
}

Nachher:

// ✅ Richtig: nur bei Bedarf laden
import dynamic from 'next/dynamic';

const ChartComponent = dynamic(() => import('./ChartComponent'), {
  loading: () => <div>Diagramm wird geladen...</div>,
  ssr: false,
});

export default function Dashboard() {
  return <ChartComponent />;
}

// ChartComponent.jsx
import { Chart } from 'chart.js';

export default function ChartComponent() {
  return <canvas ref={chartRef} />;
}

Nur Dashboard-Besucher laden Chart.js – andere Seiten unberührt.

Bilder lazy laden:

Außer LCP-Bildern sollten Bilder lazy geladen werden:

<Image
  src="/feature-image.jpg"
  width={600}
  height={400}
  loading="lazy"  // Standard, kann weggelassen werden
  alt="Feature-Übersicht"
/>

Monitoring und kontinuierliche Optimierung

Optimierung ist kein Einmal-Job – Performance braucht regelmäßige Kontrolle.

Lighthouse CI automatisieren

Manuelles Lighthouse ist zeitaufwändig und leicht vergessen. Besser: in CI/CD integrieren.

Lighthouse CI installieren:

npm install -D @lhci/cli

Konfiguration lighthouserc.js:

module.exports = {
  ci: {
    collect: {
      url: ['http://localhost:3000/', 'http://localhost:3000/products'],
      numberOfRuns: 3,  // 3 Durchläufe, Mittelwert
    },
    assert: {
      assertions: {
        'categories:performance': ['error', { minScore: 0.9 }],  // Performance ≥ 90
        'first-contentful-paint': ['error', { maxNumericValue: 2000 }],  // FCP ≤ 2 s
        'largest-contentful-paint': ['error', { maxNumericValue: 2500 }],  // LCP ≤ 2,5 s
        'cumulative-layout-shift': ['error', { maxNumericValue: 0.1 }],  // CLS < 0,1
      },
    },
    upload: {
      target: 'temporary-public-storage',
    },
  },
};

GitHub Actions:

# .github/workflows/lighthouse.yml
name: Lighthouse CI
on: [push]
jobs:
  lighthouse:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
      - run: npm install
      - run: npm run build
      - run: npm run start &
      - run: npx @lhci/cli autorun

Bei jedem Push läuft Lighthouse automatisch. Performance-Rückschritt → CI schlägt fehl.

Real User Monitoring (RUM)

Lighthouse misst im Labor – echte Nutzer erleben oft etwas anderes. Core Web Vitals aus dem Feld sammeln.

Vercel Analytics:

Bei Vercel-Deployment mit einem Klick aktivieren:

// app/layout.jsx
import { Analytics } from '@vercel/analytics/react';

export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        {children}
        <Analytics />
      </body>
    </html>
  );
}

web-vitals-Bibliothek:

Ohne Vercel Googles web-vitals nutzen:

npm install web-vitals
// app/layout.jsx
'use client';

import { useEffect } from 'react';
import { onLCP, onFID, onCLS, onINP } from 'web-vitals';

function sendToAnalytics(metric) {
  // An Analytics-Dienst senden
  fetch('/api/analytics', {
    method: 'POST',
    body: JSON.stringify(metric),
  });
}

export default function Analytics() {
  useEffect(() => {
    onLCP(sendToAnalytics);
    onINP(sendToAnalytics);
    onCLS(sendToAnalytics);
  }, []);

  return null;
}

Google Search Console:

Der Core Web Vitals-Bericht zeigt reale Nutzerdaten und markiert Seiten mit Handlungsbedarf.

Typische Fallstricke und Lösungen

Fünf häufige Fehler:

Fallstrick 1: Zu viel Client-JavaScript

Viele nutzen React für alles – die ganze Seite hängt an JavaScript. Lädt JS langsam oder gar nicht → weißer Bildschirm.

Lösung:

  • Server Components bevorzugen (Next.js 13+ Standard)
  • 'use client' nur wo nötig
  • Progressive Enhancement: Basisfunktion zuerst, Interaktivität danach

Fallstrick 2: Mobile Performance ignorieren

Schnell am Desktop heißt nicht schnell am Handy – schwächere CPU, langsamere Netze.

Lösung:

  • Lighthouse im Modus „Mobile” testen
  • Netzwerk drosseln (Chrome DevTools → Network → Throttling)
  • CPU drosseln (Chrome DevTools → Performance → CPU)

Fallstrick 3: Drittanbieter-Skripte unoptimiert

Google Analytics, Facebook Pixel, Intercom, Hotjar – jedes Skript kostet Performance.

Lösung:

  • Alles mit next/script und strategy="lazyOnload"
  • Regelmäßig prüfen: Was ist wirklich nötig?
  • Server-seitiges Tracking statt Client-Tracking erwägen

Fallstrick 4: Falsches Bildformat

Noch PNG und JPG ohne moderne Alternativen? WebP und AVIF sparen 30–50 % Volumen.

Lösung:

Next.js Image konvertiert automatisch – Server muss es unterstützen:

// next.config.js
module.exports = {
  images: {
    formats: ['image/avif', 'image/webp'],  // Moderne Formate bevorzugen
  },
};

Fallstrick 5: Server-Performance vernachlässigen

Perfektes Frontend nützt wenig, wenn der Server langsam antwortet.

Lösung:

  • Datenbankabfragen optimieren (Indizes, N+1 vermeiden)
  • Caching (Redis, CDN)
  • Server-Performance überwachen (APM: New Relic, Datadog)

Zusammenfassung

LCP – das Wichtigste:

  • priority und fetchPriority="high" für LCP-Bilder
  • next/font für Font-Ladezeiten
  • SSG und ISR bevorzugen, Server-Berechnung reduzieren
  • CDN für niedrigeren TTFB

CLS – das Wichtigste:

  • Breite und Höhe für alle Medien
  • Platz für dynamische Inhalte (Werbung, Banner)
  • Kein responsives Layout per JavaScript-Hooks
  • next/font gegen Font-Sprünge

FCP – das Wichtigste:

  • Nicht-kritische Ressourcen verzögert laden
  • Drittanbieter-Skripte mit next/script und lazyOnload
  • Große Bibliotheken und Below-the-Fold-Komponenten lazy laden

Kontinuierlich:

  • Lighthouse CI automatisieren
  • Echte Nutzerdaten (RUM) sammeln
  • Code regelmäßig prüfen und aufräumen

Performance-Optimierung ist ein Zyklus: messen → optimieren → erneut messen. Nicht alles auf einmal – kontinuierlich verbessern.

Als der Lighthouse-Score endlich über 90 lag, war die Freude groß. Die Conversion-Steigerung zeigte: Die Arbeit hat sich gelohnt.

Aktionsliste

So können Sie starten:

  1. Sofort:

    • Lighthouse für Ihr Next.js-Projekt ausführen
    • LCP-Element finden – ist priority gesetzt?
    • Code mit useMediaQuery und ähnlichem CLS-Risiko prüfen
  2. Diese Woche:

    • LCP-Bilder optimieren (priority + fetchPriority)
    • Fonts auf next/font umstellen
    • Platzhalter für dynamische Inhalte
  3. Nächste Woche:

    • Drittanbieter-Skripte auf lazyOnload
    • Große Bibliotheken und Below-the-Fold-Komponenten lazy laden
    • Lighthouse CI einrichten
  4. Dauerhaft:

    • Lighthouse-Score monatlich prüfen
    • Core Web Vitals in der Google Search Console beobachten
    • Performance-Rückschritte zeitnah beheben

Performance-Optimierung ist kein Einmal-Projekt, sondern ein laufender Prozess. Viel Erfolg!

Next.js Core Web Vitals – vollständiger Optimierungsablauf

LCP, INP und CLS optimieren und Lighthouse-Score auf 90+ bringen

⏱️ Estimated time: 8 hr

  1. 1

    Step 1: LCP (Largest Contentful Paint) optimieren

    Ziel: ≤ 2,5 s

    Optimierungsmethoden:
    • next/image für Bildoptimierung (automatische WebP/AVIF-Konvertierung)
    • priority für kritische Above-the-Fold-Bilder
    • Kritische Ressourcen vorladen (<link rel="preload">)
    • Server-Antwortzeit optimieren (CDN, Edge Functions)
    • Render-blockierende Ressourcen reduzieren (nicht-kritisches CSS/JS verzögert laden)
    • React Server Components zur Reduzierung von Client-JS

    Prüftools:
    • Lighthouse Performance-Bericht
    • Chrome DevTools Performance-Panel
    • WebPageTest (Online-Test)
  2. 2

    Step 2: INP (Interaction to Next Paint) optimieren

    Ziel: ≤ 200 ms

    Optimierungsmethoden:
    • JavaScript-Ausführungszeit reduzieren (Code-Splitting, Lazy Loading)
    • React Server Components zur Reduzierung von Client-JS
    • Event-Handling optimieren (Debouncing, Throttling, Event-Delegation)
    • Lange Tasks vermeiden (Web Workers nutzen)
    • Drittanbieter-Skripte optimieren (verzögert laden, async/defer)
    • Suspense und Streaming-Rendering nutzen

    Prüftools:
    • Chrome DevTools Performance-Panel
    • Web Vitals Chrome-Erweiterung
    • Real User Monitoring (RUM)-Tools
  3. 3

    Step 3: CLS (Cumulative Layout Shift) optimieren

    Ziel: ≤ 0,1

    Optimierungsmethoden:
    • Breite und Höhe für Bilder und Videos setzen (oder aspect-ratio nutzen)
    • Dynamisches Einfügen von Inhalten vermeiden (Platz reservieren)
    • font-display: swap gegen Layout-Sprünge durch Fonts
    • Platz für Werbung reservieren (kein Verschieben nach dem Laden)
    • CSS Grid/Flexbox statt absoluter Positionierung
    • Keine neuen Inhalte über bestehendem Content einfügen

    Prüftools:
    • Lighthouse CLS-Bericht
    • Layout-Shift-Einträge im Chrome DevTools Performance-Panel
    • WebPageTest CLS-Visualisierung
  4. 4

    Step 4: Next.js Performance-Features nutzen

    Next.js Optimierungstipps:
    • Image-Komponente für automatische Bildoptimierung
    • Font Optimization für automatische Font-Optimierung
    • React Server Components zur Reduzierung von Client-JS
    • Streaming SSR für schnelleren First Screen
    • Dynamic Imports für Code-Splitting
    • next/dynamic für verzögertes Laden von Komponenten

    Konfiguration prüfen:
    • Performance-relevante Einstellungen in next.config.js
    • Bundle-Größe prüfen (npm run build)
  5. 5

    Step 5: Monitoring und kontinuierliche Optimierung

    Monitoring-Tools:
    • Google Search Console Core Web Vitals-Bericht
    • Vercel Analytics (bei Vercel-Deployment)
    • Web Vitals Chrome-Erweiterung
    • Real User Monitoring (RUM)-Tools

    Kontinuierliche Optimierung:
    • Lighthouse-Score monatlich prüfen
    • Core Web Vitals-Bericht in der Search Console beobachten
    • Performance-Rückschritte zeitnah beheben
    • A/B-Tests für Optimierungseffekte

FAQ

Was sind die drei Kennzahlen der Core Web Vitals?
LCP (Largest Contentful Paint) ≤ 2,5 s misst die Ladeperformance; INP (Interaction to Next Paint) ≤ 200 ms misst die Interaktionsreaktion (ersetzt FID seit 2024); CLS (Cumulative Layout Shift) ≤ 0,1 misst die Layout-Stabilität. Diese drei Kennzahlen beeinflussen das Google-Ranking direkt.
Wie optimiere ich LCP?
Methoden: 1) next/image für Bildoptimierung; 2) priority für kritische Above-the-Fold-Bilder; 3) kritische Ressourcen vorladen; 4) Server-Antwortzeit optimieren; 5) render-blockierende Ressourcen reduzieren; 6) React Server Components nutzen. Ziel: LCP ≤ 2,5 s.
Was ist der Unterschied zwischen INP und FID?
INP ist seit März 2024 der neue Standard und ersetzt FID. FID misst nur die erste Interaktion, INP erfasst die Reaktionszeit aller Interaktionen. INP ist umfassender und spiegelt die reale Nutzererfahrung besser wider. Zielwert: ≤ 200 ms.
Wie vermeide ich CLS (Layout-Verschiebungen)?
Methoden: 1) Breite und Höhe für Bilder und Videos setzen; 2) dynamisches Einfügen von Inhalten vermeiden; 3) font-display: swap nutzen; 4) Platz für Werbung reservieren; 5) CSS Grid/Flexbox nutzen; 6) keine neuen Inhalte über bestehendem Content einfügen. Ziel: CLS ≤ 0,1.
Wie lange dauert es, bis Optimierungen wirken?
Technische Kennzahlen (Lighthouse-Score) sind sofort sichtbar. Geschäftskennzahlen (Conversion-Rate, Ranking) brauchen meist 1–3 Monate. Google braucht Zeit für eine Neubewertung, Nutzerverhalten muss sich erst sammeln. Kontinuierliches Monitoring und Optimierung empfohlen.
Welche Next.js-Features helfen bei der Performance?
React Server Components reduzieren Client-JS, die Image-Komponente optimiert Bilder automatisch, Font Optimization optimiert Fonts, Streaming SSR beschleunigt den First Screen, Dynamic Imports ermöglichen Code-Splitting, automatisches Code-Splitting und Tree Shaking. Diese Features konsequent nutzen verbessert die Performance deutlich.
Wie überwache ich Core Web Vitals?
Tools: 1) Core Web Vitals-Bericht in der Google Search Console (echte Nutzerdaten); 2) Lighthouse (Labordaten); 3) Web Vitals Chrome-Erweiterung; 4) Vercel Analytics (bei Vercel); 5) Real User Monitoring-Tools. Labordaten und echte Nutzerdaten gemeinsam nutzen.

13 Min. Lesezeit · Veröffentlicht am: 19. Dez. 2025 · Aktualisiert am: 14. Juli 2026

Kommentare

Melde dich mit GitHub an, um einen Kommentar zu hinterlassen

Easton BlogEaston Blog