20. September 2024

10k+ Seiten + bessere Core Web Vitals

Skalierung einer Travel-Plattform: High-Performance Static Generation im großen Maßstab

Ladezeiten und SEO-Indexierbarkeit verbessert beim Skalieren auf 10k+ Destination-Seiten

PerformanceSEOStatic GenerationNext.js

Umfang & Rahmenbedingungen

Rolle
Lead Engineer
Umfang
Performance, SEO, Static Generation im großen Maßstab

Rolle & Umfang

  • Team: Frontend + Platform-Stakeholder (repräsentativ)
  • Verantwortung: Rendering-Strategie, Performance-Ziele und Delivery-Pipeline
  • Stakeholder: Produkt, Growth/SEO und Content Owner
  • Rahmenbedingungen: tausende Seiten, Freshness-Anforderungen und Mobile-Performance

Outcome-Metriken

  • Performance: Key Pages von mehreren Sekunden auf ~unter eine Sekunde/niedrige Sekunden (repräsentativ)
  • SEO: größerer indexierbarer Umfang durch konsistente Metadaten und Hygiene strukturierter Daten
  • Lieferung: iterative Builds von Stunden auf ~10–20 Minuten reduziert (repräsentativ)

TL;DR

  • Performance & UX: Initial Load auf Key Pages von mehreren Sekunden auf ~unter eine Sekunde/niedrige Sekunden gebracht (repräsentativ). Core Web Vitals verbessert und Mobile Bounce reduziert.
  • SEO-Indexierbarkeit: Destination-Seiten zuverlässig indexierbar gemacht. Metadaten und Hygiene strukturierter Daten verbessert für reichere Such-Präsenz.
  • Liefer-Effizienz: Build- und Deployment-Overhead reduziert (Stunden → ~10–20 Minuten für iterative Builds, repräsentativ) via ISR und Caching; schnellere Iteration ermöglicht.

Kontext

Ich verantwortete die Frontend-Architektur für eine Travel-Booking-Plattform, die detaillierte Destination-Seiten für tausende Locations weltweit ausliefern musste. Jede Seite enthielt reichhaltige Inhalte (Beschreibungen, Fotos, Reviews, Empfehlungen) und musste in Suchmaschinen gut ranken.

Die bestehende Implementierung war eine clientseitig gerenderte React-App. Sie bot eine gute Experience für wiederkehrende Nutzer, hatte aber klare Nachteile: langsame initiale Loads, schlechte SEO-Performance und hohe Infrastrukturkosten, wenn SSR pro Request notwendig ist.

Problem

Die Kernherausforderungen:

SEO-Performance: Clientseitiges Rendering machte es Suchmaschinen schwer, die Inhalte zuverlässig zu indexieren. Wir verloren organischen Such-Traffic an besser optimierte Wettbewerber.

Ladezeit-Performance: First Contentful Paint (FCP) lag häufig bei 3–4 Sekunden, besonders auf Mobile. Nutzer sprangen ab, bevor Content sichtbar war.

Skalierung und Build-Zeiten: Wir mussten tausende Seiten generieren, aber klassische Static Site Generation hätte Stunden gedauert – Deployments wären praktisch unmöglich geworden.

Content-Freshness: Destination-Informationen (Preise, Verfügbarkeit, Reviews) änderten sich regelmäßig. Wir brauchten Freshness ohne Full Rebuilds.

Vorgehen

Wir migrierten auf Next.js mit einer hybriden Rendering-Strategie, die Performance, SEO und Betriebsaufwand balanciert:

Static-Generation-Strategie:

  • getStaticPaths mit fallback: 'blocking', um beliebte Destinationen beim Build zu generieren
  • Incremental Static Regeneration (ISR) mit stale-while-revalidate für weniger trafficked Pages
  • Page-Priorisierung anhand Traffic-Analytics – Top-Destinationen beim Deploy, Long Tail on-demand

Performance-Optimierungen:

  • Aggressive Image-Optimierung mit next/image (WebP, Lazy Loading, responsive Sizes)
  • Code Splitting pro Route/Komponente zur Reduktion des initialen Bundles
  • Prefetching kritischer Daten/Assets für wahrscheinliche Navigationspfade
  • CDN-Caching-Strategie mit passenden Cache-Headers (immutable Assets, kurze TTLs für HTML)

Verbesserungen an der Build-Pipeline:

  • Page Generation über mehrere Worker parallelisiert
  • Build Caching implementiert, um unveränderte Seiten nicht neu zu generieren
  • Preview Environments mit Teilmenge der Seiten für schnelleres Feedback im Development

SEO-Verbesserungen:

  • Structured Data (JSON-LD) für Destination-Seiten (Rich Snippets)
  • Optimierte Meta Tags (Title, Description, Open Graph, Twitter Cards) pro Seite
  • XML Sitemap Generation mit Priorisierung nach Seitenwert
  • Saubere Heading-Hierarchie und semantisches HTML

Ergebnisse

  • Performance & UX: Initial Load auf Key Pages von mehreren Sekunden auf ~unter eine Sekunde/niedrige Sekunden gebracht (repräsentativ), Core Web Vitals verbessert und Mobile Bounce reduziert.
  • SEO-Indexierbarkeit: Destination-Seiten zuverlässig indexierbar gemacht und Metadaten/Hygiene strukturierter Daten verbessert für reichere Such-Präsenz.
  • Liefer-Effizienz: Build- und Deployment-Overhead reduziert (Stunden → ~10–20 Minuten für iterative Builds, repräsentativ) via ISR und Caching; schnellere Iteration ermöglicht.

Stack / Rahmenbedingungen

Stack: Next.js mit TypeScript, Static Site Generation (SSG) mit Incremental Static Regeneration (ISR), CDN-Caching-Strategie, next/image Optimierung.

Rahmenbedingungen: Tausende Destination-Seiten, Freshness-Anforderungen, Mobile-Performance-Ziele und Build-Time-Limits.

Entscheidungen & Tradeoffs

  • SSG/ISR vs. SSR: Für SEO und Performance optimiert, Freshness über ISR und Cache-Strategie akzeptabel gehalten.
  • Build-Zeit vs. Vollständigkeit: High-Traffic-Seiten beim Deploy priorisiert; Long Tail on-demand generiert, um Releases praktikabel zu halten.
  • Caching vs. Korrektheit: TTLs und Revalidation getunt, um Kosten, Freshness und operative Einfachheit zu balancieren.

Was ich anders machen würde

Edge Functions früher nutzen: Wir setzten stark auf CDN-Caching, aber Personalisierung blieb teils clientseitig. Edge Functions (z. B. Vercel Edge Functions oder Cloudflare Workers) hätten mehr Logik näher an Nutzer gebracht.

Fortgeschrittenere ISR-Strategie: Unsere initiale ISR-Implementierung nutzte fixe Revalidation-Zeiten. Ein stärker event-getriebener Ansatz (Revalidate bei Content Updates) hätte bessere Freshness-Garantien geliefert.

Bessere Analytics-Integration: Wir hätten Core Web Vitals früh in Production messen sollen, um Real-World-Performance nicht nur aus Lab-Tests abzuleiten.

Inkrementellere Migration: Wir machten eine Big-Bang-Migration, was riskant war. Ein gradueller Rollout (z. B. subset of pages) hätte Risiko reduziert und schnelleres Lernen ermöglicht.

Das Projekt zeigte, dass Static Generation auf tausende Seiten skalieren kann – bei guter Performance und starker SEO. Die etablierten Muster wurden die Grundlage für weitere Content-heavy Bereiche der Plattform.