Performance & SEO

Web Performance mit Claude Code: Core Web Vitals 2026

LCP, INP, CLS optimieren — Lighthouse-Score verbessern, Image-Optimierung, Font-Loading und Bundle-Splitting mit Claude Code als Performance-Experten.

6. Mai 2026 11 min Lesezeit Performance & SEO

Web Performance ist 2026 kein optionales Nice-to-have mehr — sie ist ein handfester Ranking-Faktor bei Google und entscheidet direkt über Conversion-Rates. Studien zeigen: Jede Sekunde Ladezeit über 2,5 Sekunden kostet im Schnitt 7 % Conversion-Rate. Claude Code hat sich in diesem Bereich als erstaunlich kompetenter Partner erwiesen: Es analysiert Lighthouse-Reports, schreibt optimierten Next.js-Code und erklärt dabei jeden Schritt.

In diesem Artikel zeigen wir, wie du mit Claude Code als Sparringspartner die drei offiziellen Core Web Vitals — LCP, INP und CLS — systematisch optimierst, deinen Bundle-Overhead reduzierst und mit modernem Image- und Font-Loading den letzten Millisekunden-Vorteil herausholst.

1. Core Web Vitals 2026: Was hat sich geändert?

Google hat im Frühjahr 2025 die Gewichtung der Core Web Vitals im Page Experience Signal erneut angepasst. INP (Interaction to Next Paint) ist seit März 2024 offiziell Pflicht und hat FID vollständig abgelöst. 2026 fließen alle drei Metriken mit stärkerem Gewicht in den Rankings ein als je zuvor.

LCP 2,5 s Gut ≤ 2,5 s
INP 200 ms Gut ≤ 200 ms
CLS 0,1 Gut ≤ 0,10
TTFB 800 ms Gut ≤ 800 ms

Wo messe ich die Core Web Vitals?

Es gibt drei primäre Messquellen, die du regelmäßig im Blick behalten solltest:

Tipp web-vitals.js: Real User Monitoring im Frontend

Mit der offiziellen web-vitals-Bibliothek sendest du echte Nutzerdaten direkt aus deinem Frontend an dein Analytics-System. Claude Code schreibt dir diesen Snippet auf Anfrage sofort:

import { onLCP, onINP, onCLS, onFCP, onTTFB } from 'web-vitals'; function sendToAnalytics({ name, value, id, delta }) { navigator.sendBeacon('/api/vitals', JSON.stringify({ metric: name, value: Math.round(name === 'CLS' ? value * 1000 : value), id, delta: Math.round(delta), page: location.pathname, })); } onLCP(sendToAnalytics); // Largest Contentful Paint onINP(sendToAnalytics); // Interaction to Next Paint onCLS(sendToAnalytics); // Cumulative Layout Shift onFCP(sendToAnalytics); // First Contentful Paint onTTFB(sendToAnalytics); // Time to First Byte

Claude Code kann diesen Endpunkt vollständig für dich implementieren — inklusive Datenbankschema, Aggregations-API und Dashboard-Integration. Wichtig: Aktiviere die Felddaten-Perspektive in Google Search Console frühzeitig, denn es dauert 28 Tage bis ausreichend CrUX-Daten gesammelt sind.

Claude Code Prompt-Tipp: "Analysiere meinen Lighthouse-Report und erstelle einen priorisierten Aktionsplan für LCP, INP und CLS — sortiert nach Aufwand/Impact-Verhältnis."

2. LCP optimieren: Largest Contentful Paint unter 2,5 Sekunden

Der Largest Contentful Paint misst, wie lange es dauert, bis das größte sichtbare Element im Viewport gerendert ist — typischerweise ein Hero-Bild oder eine große Überschrift. Die häufigsten LCP-Killer sind verzögertes Ressourcen-Laden, langsame Server-Response-Zeiten und schlechte Render-Chain-Optimierung.

Preload + fetchpriority: Das LCP-Bild priorisieren

Das wichtigste LCP-Element muss der Browser so früh wie möglich kennen. Das erreichst du mit einem <link rel="preload"> im <head> kombiniert mit dem neuen fetchpriority="high"-Attribut:

LCP Hero-Bild mit maximaler Priorität laden

<!-- Im <head>: Preload für das LCP-Bild --> <link rel="preload" as="image" href="/images/hero.avif" imagesrcset="/images/hero-400.avif 400w, /images/hero-800.avif 800w, /images/hero-1200.avif 1200w" imagesizes="(max-width: 768px) 100vw, 50vw" fetchpriority="high"> <!-- Das <img>-Tag selbst --> <img src="/images/hero-800.avif" srcset="/images/hero-400.avif 400w, /images/hero-800.avif 800w, /images/hero-1200.avif 1200w" sizes="(max-width: 768px) 100vw, 50vw" width="1200" height="630" alt="Hero Bild" fetchpriority="high" loading="eager" decoding="sync" />

Critical CSS inline einbetten

Jede externe CSS-Datei ist ein Render-Blocking-Resource. Der above-the-fold-Bereich sollte Critical CSS inline im <head> haben. Claude Code hilft dir, mit Tools wie critters oder critical diesen Prozess zu automatisieren:

// next.config.js — Critical CSS mit critters automatisieren const withCritters = require('critters/webpack'); module.exports = withCritters({ experimental: { optimizeCss: true, // Next.js integriertes Critical CSS }, images: { formats: ['image/avif', 'image/webp'], minimumCacheTTL: 86400, }, });

Server Response Time (TTFB) verbessern

LCP beginnt erst nach dem ersten Byte vom Server. Ein TTFB über 800 ms ist häufig der versteckte Grund für schlechte LCP-Werte — auch wenn das Frontend optimiert ist.

LCP TTFB-Checkliste für Next.js / Node.js

LCP Optimierungs-Checkliste

3. INP optimieren: Interaction to Next Paint unter 200 ms

INP ist die schwierigste der drei Core Web Vitals — und die, bei der Claude Code am meisten Mehrwert bringt. Die Metrik misst die Latenz zwischen Nutzerinteraktion (Klick, Touch, Tastendruck) und dem nächsten Frame, den der Browser rendert. Über 200 ms fühlt sich die Seite für Nutzer träge an.

Long Tasks aufspüren und aufteilen

Der häufigste INP-Killer sind "Long Tasks" — JavaScript-Ausführungsblöcke die länger als 50 ms dauern und den Main Thread blockieren. Chrome DevTools → Performance Tab zeigt diese als rote Blöcke an.

INP scheduler.yield(): Long Tasks aufteilen

Seit Chrome 115 gibt es die offizielle scheduler.yield()-API. Sie gibt dem Browser kurz die Kontrolle zurück, damit er Nutzerinteraktionen verarbeiten kann:

// VORHER: Ein langer Block blockiert den Main Thread async function processLargeDataset(items) { for (const item of items) { expensiveOperation(item); // blockiert bis zu 500ms! } } // NACHHER: Mit scheduler.yield() in Chunks aufteilen async function processLargeDataset(items) { for (let i = 0; i < items.length; i++) { expensiveOperation(items[i]); // Alle 5 Items: dem Browser Kontrolle zurückgeben if (i % 5 === 0) { await scheduler.yield(); } } }

React: useTransition für nicht-dringende Updates

In React-Anwendungen ist useTransition das wichtigste Werkzeug gegen schlechte INP-Werte. Es markiert State-Updates als niedrig priorisiert, sodass der Browser Nutzerinteraktionen dazwischenschieben kann:

import { useState, useTransition } from 'react'; function SearchComponent() { const [query, setQuery] = useState(''); const [results, setResults] = useState([]); const [isPending, startTransition] = useTransition(); const handleInput = (e) => { const value = e.target.value; setQuery(value); // sofort aktualisieren (high priority) startTransition(() => { // Teure Suche als low priority markieren setResults(performExpensiveSearch(value)); }); }; return ( <div> <input value={query} onChange={handleInput} /> {isPending && <Spinner />} <ResultsList results={results} /> </div> ); }

Web Workers für CPU-intensive Aufgaben

Berechnungen die mehr als 50 ms dauern — wie Datei-Parsing, Krypto-Operationen oder komplexe Datenverarbeitung — gehören in einen Web Worker. Dort laufen sie auf einem separaten Thread, ohne den Main Thread zu blockieren:

INP Web Worker Boilerplate mit Comlink

// worker.ts — läuft auf separatem Thread import * as Comlink from 'comlink'; const api = { parseCSV(csvString: string) { // CPU-intensive Verarbeitung — blockiert NICHT den Main Thread return csvString.split('\n').map(row => row.split(',')); } }; Comlink.expose(api); // main.ts — Main Thread import * as Comlink from 'comlink'; const worker = new Worker(new URL('./worker.ts', import.meta.url)); const api = Comlink.wrap(worker); // Aufruf wie normale async Funktion — Main Thread bleibt frei const data = await api.parseCSV(largeCSVString);
Claude Code Prompt-Tipp: "Zeig mir alle Event Handler in meiner App die mehr als 50 ms dauern könnten und schlage useTransition oder Web Worker Lösungen vor."

4. CLS optimieren: Cumulative Layout Shift unter 0,1

Layout Shifts — wenn Inhalte beim Laden springen — sind für Nutzer extrem frustrierend und werden von Google entsprechend bestraft. Ein CLS-Score über 0,1 ist ein klares Zeichen, dass Dimensionen im HTML fehlen oder Inhalte nachgeladen werden ohne Platzhalterfläche.

Bildgrößen immer angeben

Jedes <img> ohne width und height verursacht Layout Shifts, weil der Browser die benötigte Fläche nicht kennt, bevor das Bild geladen ist:

CLS Bild-Dimensionen und aspect-ratio

<!-- FALSCH: Kein width/height → Layout Shift beim Laden --> <img src="foto.jpg" alt="Produktfoto" class="product-image" /> <!-- RICHTIG: Exakte Pixel oder aspect-ratio --> <img src="foto.jpg" alt="Produktfoto" width="800" height="600" class="product-image" loading="lazy" /> /* CSS: aspect-ratio als Fallback */ .product-image { width: 100%; height: auto; aspect-ratio: 4 / 3; /* hält Platz frei auch wenn width/height fehlt */ }

Font Display Swap: Keine FOIT mehr

Flash of Invisible Text (FOIT) und Flash of Unstyled Text (FOUT) sind häufige CLS-Quellen. Die beste Strategie für 2026 ist font-display: optional bei self-hosted Fonts — der Browser verwendet die System-Schrift falls der Font nicht innerhalb von 100 ms geladen ist:

/* @font-face mit optimalem font-display */ @font-face { font-family: 'Inter'; src: url('/fonts/inter-var.woff2') format('woff2'); font-weight: 100 900; font-style: normal; font-display: optional; /* kein Layout Shift, keine FOIT */ unicode-range: U+0000-00FF, U+0131, U+0152-0153; } /* Preconnect für Google Fonts (falls externe Fonts nötig) */

Skeleton Screens statt leerem Content

Wenn Inhalte per API geladen werden, müssen Skeleton-Screens die genauen Dimensionen des finalen Inhalts reservieren. Sonst verschiebt sich die Seite sobald die Daten eintreffen:

CLS React Skeleton mit fixer Höhe

// Skeleton-Komponente mit exakter Höhe function ProductCardSkeleton() { return ( <div className="product-card" aria-busy="true"> {/* Bild-Platzhalter: exakt gleiche Dimensionen wie echtes Bild */} <div style={{ width: '100%', aspectRatio: '4/3', background: '#e2e8f0' }} /> <div style={{ height: '24px', background: '#e2e8f0', margin: '12px 0' }} /> <div style={{ height: '16px', width: '60%', background: '#e2e8f0' }} /> </div> ); } // Verwendung: function ProductCard({ id }) { const { data, isLoading } = useSWR(`/api/products/${id}`); if (isLoading) return <ProductCardSkeleton />; return <div className="product-card">{data.name}</div>; }

Dynamische Inhalte: Platzhalter mit min-height

/* Banner/Ad Container mit garantierter Mindesthöhe */ .ad-container { min-height: 90px; /* IAB Standard Leaderboard */ contain: layout; /* CSS Containment: Layout-Shifts isolieren */ } .cookie-banner { position: fixed; /* fixed = kein CLS, da kein Document-Flow */ bottom: 0; width: 100%; } /* Smooth scroll vermeidet visuell wahrgenommene Shifts */ html { scroll-behavior: smooth; }

5. Bundle-Optimierung: Code Splitting & Tree Shaking

Ein großes JavaScript-Bundle ist der häufigste Grund für schlechte LCP- und INP-Werte gleichzeitig: Der Browser muss das Bundle herunterladen, parsen und ausführen, bevor die Seite interaktiv wird. Claude Code hilft dir, dein Bundle systematisch zu analysieren und zu reduzieren.

Bundle Analyzer: Was frisst den Platz?

Bundle @next/bundle-analyzer einrichten

// Installation npm install --save-dev @next/bundle-analyzer // next.config.js const withBundleAnalyzer = require('@next/bundle-analyzer')({ enabled: process.env.ANALYZE === 'true', }); module.exports = withBundleAnalyzer({ // ... deine Konfiguration }); // package.json { "scripts": { "analyze": "ANALYZE=true next build" } } // Ausführen: npm run analyze // Öffnet interaktive Treemap in Browser

Dynamic Import: Code Splitting per Route

Große Komponenten die nicht auf jeder Seite gebraucht werden, sollten dynamisch importiert werden. Next.js macht das mit next/dynamic sehr einfach:

import dynamic from 'next/dynamic'; // Schwere Charting-Bibliothek (z.B. recharts, chart.js, D3) const HeavyChart = dynamic( () => import('../components/HeavyChart'), { loading: () => <div style={{ height: '300px', background: '#f1f5f9' }} />, ssr: false, // kein SSR für Client-only Bibliotheken } ); // Rich Text Editor — nur auf Edit-Seiten laden const RichTextEditor = dynamic( () => import('../components/RichTextEditor'), { ssr: false } ); export default function Page({ isEditing }) { return ( <main> {isEditing && <RichTextEditor />} <HeavyChart data={chartData} /> </main> ); }

Tree Shaking: Nur das importieren was gebraucht wird

Bundle Tree Shaking Best Practices

// FALSCH: Gesamte Bibliothek importieren (tree-shaking blockiert) import _ from 'lodash'; // +70 KB! import * as Icons from '@heroicons/react/24/outline'; // RICHTIG: Named Imports für Tree Shaking import { debounce, throttle } from 'lodash-es'; // ESM version! import { HomeIcon, UserIcon } from '@heroicons/react/24/outline'; // Date-fns statt moment.js (4x kleiner, tree-shakeable) import { format, parseISO } from 'date-fns'; import { de } from 'date-fns/locale'; // Alternativ: native Intl.DateTimeFormat (0 KB Bundle-Overhead) const fmt = new Intl.DateTimeFormat('de-DE', { dateStyle: 'long' }); fmt.format(new Date()); // "6. Mai 2026"

Preloading Strategy: Was wirklich gebraucht wird

// Route-basiertes Prefetching mit Next.js Link import Link from 'next/link'; // prefetch={false} für seltene Seiten (spart Bandbreite) <Link href="/admin/settings" prefetch={false}>Einstellungen</Link> // Intersection Observer für intelligentes Prefetching const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { // Route prefetchen wenn Link sichtbar wird router.prefetch(entry.target.getAttribute('href')); } }); }, { rootMargin: '200px' }); // 200px vor Viewport

6. Image & Font-Optimierung: Der letzte Schliff

Nachdem LCP, INP und CLS optimiert sind, bringen Image- und Font-Strategien den letzten entscheidenden Geschwindigkeitsvorteil. Moderne Formate wie AVIF können Bilder um 50–70 % kleiner machen als JPEG — ohne sichtbaren Qualitätsverlust.

next/image: Automatische Bildoptimierung

Image next/image mit allen Performance-Attributen

import Image from 'next/image'; // Hero-Bild: priority=true für LCP, keine lazy loading <Image src="/images/hero.jpg" alt="Hero Bild" width={1200} height={630} priority // = fetchpriority="high" + preload sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw" quality={85} // Standard: 75, für Hero-Bilder: 85-90 placeholder="blur" blurDataURL="data:image/jpeg;base64,..." // LQIP /> // Product-Bilder: lazy, mit korrektem sizes-Attribut <Image src={product.image} alt={product.name} fill sizes="(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 25vw" style={{ objectFit: 'cover' }} />

AVIF und WebP: Moderne Bildformate

// next.config.js: AVIF als primäres Format konfigurieren module.exports = { images: { formats: ['image/avif', 'image/webp'], // AVIF zuerst deviceSizes: [640, 750, 828, 1080, 1200, 1920], imageSizes: [16, 32, 48, 64, 96, 128, 256], minimumCacheTTL: 86400 * 30, // 30 Tage Cache remotePatterns: [ { protocol: 'https', hostname: 'images.unsplash.com' }, ], }, }; // Vanilla HTML: picture-Element für Browser-Kompatibilität

Image picture-Element für maximale Kompatibilität

<picture> <!-- AVIF für moderne Browser (Chrome 85+, Firefox 93+) --> <source type="image/avif" srcset="/img/hero-400.avif 400w, /img/hero-800.avif 800w, /img/hero-1200.avif 1200w" sizes="(max-width: 768px) 100vw, 50vw" /> <!-- WebP Fallback --> <source type="image/webp" srcset="/img/hero-400.webp 400w, /img/hero-800.webp 800w, /img/hero-1200.webp 1200w" sizes="(max-width: 768px) 100vw, 50vw" /> <!-- JPEG Ultimate Fallback --> <img src="/img/hero-800.jpg" alt="Hero" width="800" height="420" fetchpriority="high" loading="eager" /> </picture>

Self-hosted Google Fonts: Keine externen DNS-Lookups

Google Fonts über den offiziellen CDN zu laden kostet TTFB-Zeit durch DNS-Lookup + TLS-Handshake. Die Lösung: Fonts herunterladen, selbst hosten und mit optimalem font-display einbinden:

/* Optimiertes @font-face Setup für self-hosted Fonts */ @font-face { font-family: 'Inter'; src: url('/fonts/inter-var.woff2') format('woff2-variations'); font-weight: 100 900; font-display: optional; /* optional: kein FOIT, kein CLS */ font-style: normal; } /* Preload im <head> */

Font Preload + Preconnect im <head>

<head> <!-- Self-hosted Font preloaden --> <link rel="preload" href="/fonts/inter-var.woff2" as="font" type="font/woff2" crossorigin="anonymous" /> <!-- Falls Google Fonts DOCH nötig: preconnect --> <link rel="preconnect" href="https://fonts.googleapis.com" /> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> <!-- DNS Prefetch für Third-Party Scripts --> <link rel="dns-prefetch" href="https://www.googletagmanager.com" /> </head>

Next.js Font Optimierung (next/font)

import { Inter, JetBrains_Mono } from 'next/font/google'; // next/font: automatisch self-hosted, kein external request const inter = Inter({ subsets: ['latin', 'latin-ext'], // Nur nötige Zeichen display: 'optional', // CLS-safe variable: '--font-inter', // CSS Custom Property preload: true, }); const mono = JetBrains_Mono({ subsets: ['latin'], display: 'swap', variable: '--font-mono', preload: false, // Monospace nur bei Bedarf }); export default function RootLayout({ children }) { return ( <html lang="de" className={`${inter.variable} ${mono.variable}`}> <body className={inter.className}>{children}</body> </html> ); }

Image & Font Optimierungs-Checkliste

Claude Code als dein Performance-Experte

Claude Code analysiert deinen Lighthouse-Report, findet die Performance-Bottlenecks und schreibt den optimierten Code — von fetchpriority über scheduler.yield bis zu dynamischen Imports. Teste es 14 Tage kostenlos.

Kostenlos testen — 14 Tage

Fazit: Mit Claude Code zum Performance-Champion

Core Web Vitals 2026 sind kein Mystery mehr, wenn du einen kompetenten Partner hast, der nicht nur die Metriken versteht, sondern auch sofort den korrekten Code schreibt. Die wichtigsten Hebel im Überblick:

Die gute Nachricht: Alle diese Optimierungen sind klar definiert, gut dokumentiert — und Claude Code kann dir jeden einzelnen Schritt implementieren. Starte mit einem Lighthouse-Audit deiner Startseite, identifiziere den größten Bottleneck und lass Claude Code den Rest erledigen.

Dieser Artikel wurde am 6. Mai 2026 veröffentlicht. Performance-Metriken und Browser-APIs entwickeln sich weiter — prüfe die web.dev/vitals Dokumentation für aktuelle Grenzwerte.