
In Next.js (App Router) ist der größte Performance-Hebel oft nicht „noch mehr Caching“, sondern weniger unnötiges Client-JavaScript.
Dieser Guide hilft dir, Server Components und Client Components so aufzuteilen, dass:
- wichtige Inhalte und Links zuverlässig im HTML landen (SEO)
- du Hydration- und JS-Kosten senkst (Core Web Vitals)
- du trotzdem saubere Interaktion behältst (UX)
Mehr Kontext (größeres Gesamtbild): Next.js SEO 2026
1) Grundlagen: Was ist was?
Server Components (Default)
Server Components werden auf dem Server gerendert. Sie sind ideal für:
- Content (Text, Überschriften, Listen)
- interne Links und Navigation
- Layout und Struktur
- Daten laden (CMS/DB/API) und daraus HTML bauen
Client Components ("use client")
Client Components laufen im Browser und werden hydratisiert. Du brauchst sie, wenn du:
- State / Interaktion brauchst (Tabs, Filter, Slider, Form-UX)
- Browser-APIs nutzt (z.B.
window,localStorage) - Event Handler (
onClick,onSubmit) verwendest
Merksatz: Server rendert. Client interagiert.
2) Warum das SEO beeinflusst (ohne Mythen)
Google kommt heute gut mit JS klar – aber für stabiles SEO willst du, dass der „wichtigste Teil“ sofort da ist.
Was für SEO in der Praxis zählt:
- Hauptinhalt im initialen HTML (Überschrift, Text, Produkt/Leistung, FAQ)
- interne Links im HTML (Navigation, Teaser, Breadcrumbs)
- saubere Metadaten (Title/Description/Canonical)
Wenn diese Dinge erst nach Client-JS entstehen, wird es unnötig riskant (und oft auch langsamer).
3) Performance: Das echte Problem heißt Hydration
Jede Client Component kann bedeuten:
- mehr JS-Download
- mehr Parse/Execute
- Hydration-Kosten (CPU) bevor Interaktion „smooth“ wird
Das trifft häufig:
- INP (Interaktionslatenz)
- LCP (wenn große UI-Blöcke erst nach JS „fertig“ wirken)
- indirekt Conversion (weil Seiten „zäh“ sind)
4) Entscheidungs-Guide: Server oder Client?
Nutze diese Entscheidungshilfe pro UI‑Teil:
Nimm Server Components, wenn …
- es nur Darstellung ist (Text/Bilder/Links)
- der Content aus Datenquellen kommt
- SEO‑relevante Inhalte/Links betroffen sind
Nimm Client Components, wenn …
- Nutzer wirklich interagieren (State, Events)
- du Browser-APIs brauchst
- du UI-Logik brauchst, die ohne JS nicht geht
Typische „Zwischenfälle“ (und die richtige Lösung)
- „Eine Seite braucht einen kleinen Filter“ → Filter als isolierte Client‑Insel, Seite bleibt Server.
- „Ein Button öffnet ein UI‑Element“ → nur das UI‑Element/Widget als Client, Rest Server.
5) Anti-Patterns, die SEO & CWV regelmäßig kaputt machen
Anti-Pattern A: Ganze Seite ist Client wegen eines Widgets
Wenn du eine komplette Page/Section als Client markierst, nur weil irgendwo ein kleines interaktives Element sitzt, bezahlst du mit unnötigem JS.
Besser: Interaktion isolieren.
Anti-Pattern B: Hauptcontent kommt erst nach useEffect
Wenn Text/Links erst nach einem clientseitigen Fetch erscheinen, sieht der Nutzer (und oft auch Google) initial „zu wenig“.
Besser: Daten serverseitig laden und als HTML rendern.
Anti-Pattern C: Link-Strukturen nur als „JS-Menü"
Wenn Navigation/Teaser-Links primär über Client-State oder Events entstehen, kann die interne Verlinkung schwächer werden.
Besser: Links als echte <a> im HTML – Interaktion nur „drüber“ legen.
6) Praxis-Rezept: So refactorst du ohne Risiko
Schritt 1: Server-first für Page und Layout
Die Page rendert Content/Links serverseitig.
Schritt 2: Client nur für die Interaktions-Insel
Beispiel-Pattern (vereinfacht):
// app/beispiel/page.tsx (Server Component)
import Widget from "./Widget";
export default async function Page() {
const data = await fetch("https://example.com/api").then((r) => r.json());
return (
<main>
<h1>SEO-relevanter Inhalt steht im HTML</h1>
<p>Dieser Text ist sofort da, ohne Client-JS.</p>
<Widget initialItems={data.items} />
</main>
);
}
// app/beispiel/Widget.tsx (Client Component)
"use client";
import { useMemo, useState } from "react";
export default function Widget({ initialItems }) {
const [query, setQuery] = useState("");
const items = useMemo(
() => initialItems.filter((x) => x.name.toLowerCase().includes(query.toLowerCase())),
[initialItems, query]
);
return (
<section>
<label>
Filtern
<input value={query} onChange={(e) => setQuery(e.target.value)} />
</label>
<ul>{items.map((x) => <li key={x.id}>{x.name}</li>)}</ul>
</section>
);
}
Ziel: Die Seite bleibt „crawl- und indexierbar“ aus dem Stand, und nur das Widget braucht Hydration.
Schritt 3: Vorher/Nachher messen
Messe gezielt:
- LCP (größtes Element)
- INP (Interaktionslatenz)
- JS-Transfer/Bundles (wie viel kommt wirklich im Client an?)
Wenn du nur eine Sache tun willst: identifiziere die größten Client-Blöcke und splitte sie in Server + kleine Client‑Inseln.
7) Mini-Checkliste (zum Abhaken)
- Wichtigste Inhalte/Links stehen im initialen HTML
- Metadaten/Canonical sind sauber (nicht „erst im Client“)
- Nur interaktive Teile sind Client Components
- Kein Fetch für Hauptcontent in
useEffect - CWV vor/nach Refactor gemessen
Nächster Schritt
Wenn du willst, machen wir eine kurze Audit-Session, finden die größten Client-JS-Treiber und schneiden JS raus, ohne Design zu verlieren.


