almessadi.
Zur Übersicht

React Server-Komponenten vs SSR: Wo die tatsächliche Grenze liegt_

SSR und React Server-Komponenten lösen verwandte Probleme, sind aber nicht dasselbe Mechanismus. Das Verständnis der Grenze hilft bei der Bundle-Größe, dem Datenfluss und der Architektur.

Veröffentlicht20. März 2024
Lesezeit9 min read

React Server-Komponenten und serverseitiges Rendering sind leicht zu verwechseln, da sie oft in derselben Anwendung verwendet werden.

Sie sind verwandt. Sie sind nicht dasselbe.

Wenn Sie sie als austauschbar betrachten, enden Sie mit verwirrenden Architekturentscheidungen und einem Codebase, die mehr Client-JavaScript enthält, als nötig.

## SSR löst die anfängliche Darstellung

Traditionelles SSR rendert HTML auf dem Server, sodass der Browser etwas Nützliches anzeigen kann, bevor die Client-Anwendung vollständig hydratisiert.

Das ist wertvoll für:

- erstes Rendering
- Crawlability
- wahrgenommene Leistung

Aber SSR beseitigt nicht die Notwendigkeit von Client-JavaScript. Wenn die Seite interaktiv ist, benötigt der Browser immer noch den Code, der erforderlich ist, um die Benutzeroberfläche zu hydratisieren.

Das ist der entscheidende Punkt, den viele Teams übersehen: serverseitig gerendertes HTML ist nicht dasselbe wie die Ausführung von Komponenten ausschließlich auf dem Server.

## Server-Komponenten lösen die Platzierung von Bundles

React Server-Komponenten ändern, wo einige Komponentenlogik leben darf.

Eine Server-Komponente wird auf dem Server ausgeführt, kann direkt auf serverseitige Ressourcen zugreifen und liefert ihre eigene Implementierung nicht an den Browser aus.

Das macht sie nützlich für:

- datenbankgestützte UI-Zusammenstellung
- kostspielige Inhaltsumwandlung
- das Halten serverseitiger Abhängigkeiten aus dem Client-Bundle

Ein einfaches Beispiel:

```tsx
import { db } from "@/lib/db";
import MarkdownIt from "markdown-it";

const md = new MarkdownIt();

export default async function PostBody({ slug }: { slug: string }) {
  const post = await db.post.findUniqueOrThrow({ where: { slug } });
  const html = md.render(post.body);

  return <article dangerouslySetInnerHTML={{ __html: html }} />;
}

Wenn dies eine Server-Komponente bleibt, benötigt der Browser den Datenbank-Client oder den Markdown-Parser nicht, nur um den Rest der Seite interaktiv zu machen.

Hydration existiert weiterhin

Server-Komponenten beseitigen nicht die Client-Komponenten. Sie ermöglichen es, diese gezielter zu verwenden.

In dem Moment, in dem Sie Browser-APIs, lokalen Zustand oder Ereignis-Handler benötigen, überschreiten Sie die Grenze zum Client:

"use client";

import { useState } from "react";

export function LikeButton() {
  const [liked, setLiked] = useState(false);

  return (
    <button onClick={() => setLiked((value) => !value)}>
      {liked ? "Gefällt mir" : "Gefällt mir nicht"}
    </button>
  );
}

Diese Komponente wird weiterhin auf dem Client hydratisiert. Das Ziel ist nicht "null JavaScript überall". Das Ziel ist es, JavaScript nur dort auszuliefern, wo der Browser es tatsächlich benötigt.

Die Architekturentscheidung

Die praktische Frage ist nicht "sollten wir SSR oder RSC verwenden?" In modernen Next.js-Anwendungen verwenden Sie oft beides.

Die bessere Frage ist:

"Welche Teile dieses Baums müssen im Browser ausgeführt werden?"

Wenn die Antwort "sehr wenig" lautet, können Server-Komponenten die Bundle-Größe und das Abhängigkeitschaos erheblich reduzieren.

Wenn der Großteil der Seite hochgradig interaktiv ist, helfen Server-Komponenten weiterhin beim Datenzugriff und der Komposition, aber sie verwandeln ein interaktives Dashboard nicht magic in eine serverseitige Seite.

Was schiefgeht in realen Codebasen

Die häufigsten Fehlerarten sind vorhersehbar:

  • das Markieren ganzer Routen mit "use client", weil ein Teil Interaktivität benötigt
  • das Übertragen großer serialisierter Objekte über die Server/Client-Grenze
  • das versehentliche Importieren serverseitiger Module in Client-Code
  • die Annahme, dass Server-Komponenten alle API-Grenzen ersetzen

Die Disziplin besteht darin, die Grenze schmal zu halten.

Verwenden Sie Server-Komponenten für:

  • Datenabruf
  • serverseitige Bibliotheken
  • nicht-interaktive Inhaltszusammenstellung

Verwenden Sie Client-Komponenten für:

  • Ereignis-Handler
  • browserexklusive APIs
  • lokalen Interaktionszustand

Diese Aufteilung ist nicht ideologisch. Es lässt sich einfach leichter skalieren.

Weiterführende Literatur