React Server Components: Ein praktischer Deep Dive

React Server Components: Ein praktischer Deep Dive

Wie RSC-Grenzen, Streaming und die Client/Server-Trennung im Next.js App Router funktionieren — und wann man eine Client-Komponente braucht.

12. Juni 202612 Min. LesezeitVon Shehzad Asadullah

React Server Components stellen einen der bedeutendsten architektonischen Wandel im React-Ökosystem seit Hooks dar. In Kombination mit dem Next.js App Router ermöglichen sie, Komponenten standardmäßig auf dem Server zu rendern, nur die serialisierte Ausgabe an den Client zu senden und clientseitiges JavaScript für die Interaktionen zu reservieren, die es wirklich benötigen. Zu verstehen, wo Server Components enden und Client Components beginnen, ist entscheidend für den Aufbau schneller, wartbarer Anwendungen im Jahr 2026.

Diagramm, das den Datenfluss von React Server Components zwischen Server- und Client-Grenzen veranschaulicht
Server Components holen Daten und rendern auf dem Server, während Client Components die Interaktivität an der Grenze übernehmen.

Was sind React Server Components?

React Server Components, oft als RSC abgekürzt, sind Komponenten, die ausschließlich auf dem Server während einer Anfrage oder zur Build-Zeit ausgeführt werden. Im Gegensatz zum traditionellen serverseitigen Rendering, bei dem die gesamte Seite auf dem Client hydriert wird, sendet RSC eine kompakte serialisierte Darstellung namens React-Flight-Payload. Der Client empfängt diese Payload und rekonstruiert die Benutzeroberfläche, ohne den Quellcode der Komponente oder ihre Abhängigkeiten herunterzuladen.

Dieses Modell bietet mehrere praktische Vorteile für Produktionsanwendungen:

  • Reduzierte Bundle-Größe — Server-only-Abhängigkeiten werden nie an den Browser ausgeliefert.
  • Direkter Datenzugriff — Komponenten können Datenbanken und Dateisysteme abfragen, ohne Anmeldedaten über API-Routen preiszugeben.
  • Automatisches Code-Splitting — Jede Server-Component-Grenze schafft einen natürlichen Split-Punkt.
  • Verbesserte Time to First Byte — Streaming ermöglicht das Rendern der Shell, während langsamere Daten aufgelöst werden.

Das mentale Modell ist unkompliziert: Betrachten Sie Server Components als die Standard-Rendering-Schicht und Client Components als optionale Inseln der Interaktivität, die im gesamten Baum verteilt sind.

RSC-Grenzen in Next.js verstehen

Im Next.js App Router ist jede Datei im app-Verzeichnis eine Server Component, es sei denn, Sie fügen die "use client"-Direktive am Anfang der Datei hinzu. Diese Direktive erstellt eine Client-Grenze. Alles, was von dieser Datei importiert wird, wird Teil des Client-Bundles, und alle als Props übergebenen Kinder können durch eine Technik namens Composition weiterhin serverseitig gerendert werden.

Composition über Grenzen hinweg

Eines der leistungsstärksten Muster ist das Übergeben von Server Components als Kinder an Client Components. Die Server Component wird zuerst gerendert, und ihre Ausgabe wird in den Slot der Client Component gestreamt. Dies vermeidet die häufige Falle, eine gesamte Seite als Client Component zu markieren, nur weil ein kleiner Abschnitt State oder Event-Handler benötigt.

// ServerComponent.tsx (no directive — runs on server)
async function ProductList() {
  const products = await db.query("SELECT * FROM products");
  return (
    <ul>
      {products.map((p) => (
        <li key={p.id}>{p.name}</li>
      ))}
    </ul>
  );
}

// ClientWrapper.tsx
"use client";
export function ClientWrapper({ children }: { children: React.ReactNode }) {
  const [expanded, setExpanded] = useState(false);
  return (
    <div>
      <button onClick={() => setExpanded(!expanded)}>Toggle</button>
      {expanded && children}
    </div>
  );
}

// page.tsx (Server Component)
export default function Page() {
  return (
    <ClientWrapper>
      <ProductList />
    </ClientWrapper>
  );
}

Beachten Sie, dass ProductList niemals eine Client Component wird, obwohl sie innerhalb eines interaktiven Wrappers liegt. Der Server rendert sie, serialisiert das Ergebnis, und der Client empfängt das fertige Markup.

Streaming und Suspense

Next.js nutzt die Streaming-Fähigkeiten von React, um HTML schrittweise an den Browser zu senden. Wenn Sie asynchrone Server Components in <Suspense>-Grenzen einwickeln, kann das Framework sofort Fallback-UI anzeigen, während langsamere Abschnitte im Hintergrund aufgelöst werden.

Streaming ist besonders effektiv für Seiten mit heterogenen Datenquellen. Eine schnelle Caching-Schicht kann in Millisekunden aufgelöst werden, während eine komplexe Aggregationsabfrage mehrere Sekunden dauert. Ohne Streaming starrt der Benutzer auf einen leeren Bildschirm, bis alles abgeschlossen ist. Mit Streaming erscheinen Navigations-Chrome, Layout und gecachte Inhalte sofort.

  • Platzieren Sie <Suspense>-Grenzen um unabhängige Datenabruf-Bereiche.
  • Verwenden Sie aussagekräftige Fallback-UI — Skeleton-Loader schlagen generische Spinner.
  • Verschachteln Sie Grenzen für granulare Kontrolle darüber, was zuerst gestreamt wird.
  • Kombinieren Sie mit loading.tsx-Dateien für routenbezogene Fallbacks.

Die Kombination aus RSC und Streaming verändert grundlegend, wie Sie über die Seitenlade-Performance denken. Anstatt eine einzelne Waterfall-Anfrage zu optimieren, gestalten Sie Seiten als eine Reihe unabhängig streambarer Segmente.

Wann Client Components verwenden

Trotz des Server-First-Standards bleiben Client Components unverzichtbar. Jede Funktion, die auf Browser-APIs, lokalen State, Effects oder Event-Handler angewiesen ist, erfordert die Client-Grenze. Das Ziel ist nicht, Client Components zu eliminieren, sondern ihren Footprint zu minimieren.

Greifen Sie zu "use client", wenn Sie eines der Folgenden benötigen:

  • Event-Handler — onClick, onChange, onSubmit und ähnliche DOM-Interaktionen.
  • React-Hooks — useState, useEffect, useReducer, useContext und benutzerdefinierte Hooks, die von ihnen abhängen.
  • Nur-Browser-APIs — localStorage, Geolocation, IntersectionObserver und Web Audio.
  • Drittanbieter-Bibliotheken — Viele Charting-, Mapping- und Animationsbibliotheken setzen eine Browser-Umgebung voraus.

Eine praktische Heuristik ist, die Client-Grenze so weit wie möglich im Komponentenbaum nach unten zu schieben. Anstatt eine gesamte Dashboard-Seite als Client Component zu markieren, extrahieren Sie das interaktive Diagramm oder Filter-Panel in eine kleine Client-Insel und behalten das umgebende Layout, Header und Datentabellen auf dem Server.

Data-Fetching-Muster

Server Components können Daten direkt mit async/await auf Komponentenebene abrufen. Für serverseitige Reads sind weder useEffect noch eine separate Data-Fetching-Bibliothek erforderlich. Next.js erweitert dies mit Caching-Semantik über die fetch-API und den unstable_cache-Helper.

// Direct async fetch in a Server Component
async function BlogPost({ slug }: { slug: string }) {
  const post = await fetch(`https://api.example.com/posts/${slug}`, {
    next: { revalidate: 3600 },
  }).then((res) => res.json());

  return (
    <article>
      <h1>{post.title}</h1>
      <p>{post.body}</p>
    </article>
  );
}

Für Mutationen integrieren sich React-19-Actions natürlich mit Server Components. Sie definieren Server Actions mit der "use server"-Direktive und rufen sie aus Client-Formularen auf, ohne manuell API-Endpunkte zu konstruieren. Dies schließt die Lücke zwischen Server-Rendering und serverseitigen Mutationen auf typsichere, kolokalisierte Weise.

Häufige Fallstricke und Best Practices

Teams, die neu in RSC sind, stoßen oft auf wiederkehrende Fehler. Das Übergeben nicht serialisierbarer Werte wie Funktionen oder Klasseninstanzen von Server- zu Client Components löst Laufzeitfehler aus. Das Importieren von Server-only-Modulen in Client Components verursacht Build-Fehler. Und das Markieren großer Komponentenbäume als Client Components macht den Zweck der Architektur vollständig zunichte.

Übernehmen Sie diese Praktiken, um auf Kurs zu bleiben:

  • Behalten Sie Server Components als Standard bei und fügen Sie Client-Grenzen gezielt hinzu.
  • Kolokalisieren Sie Data Fetching mit den Komponenten, die die Daten konsumieren.
  • Verwenden Sie TypeScript, um Serialisierungsprobleme zur Compile-Zeit zu erkennen.
  • Profilieren Sie Ihr Client-Bundle regelmäßig, um sicherzustellen, dass Server Components ihre Arbeit leisten.
  • Dokumentieren Sie Grenzentscheidungen in Ihrer Codebasis, damit das Team Konsistenz beibehält.

React Server Components sind kein Allheilmittel, aber sie bieten ein kohärentes Modell für den Aufbau von Anwendungen, die standardmäßig schnell sind. Das Beherrschen von Grenzen, Streaming und dem Server-Client-Composition-Muster zahlt sich bei jedem Projekt aus, das Sie mit dem Next.js App Router ausliefern.

Hat es dir gefallen?

Hast du ein Projekt oder eine Idee? Ich würde gern davon hören.

Kontakt aufnehmen