Start / Seminare / Next.js 16 Full-Stack-Entwicklung mit React und TypeScript

Modul

Datenzugriff und Streaming

7 Kapitel in diesem Modul-Video · Laufzeit

Vertonung mit synthetischer Stimme · Inhalte redaktionell verantwortet · © 2026 HECKER CONSULTING, alle Rechte vorbehalten

Transkript

Der gesprochene Text dieses Moduls zum Mitlesen, Überfliegen und Durchsuchen. Ein Klick auf einen Zeitstempel springt an die Stelle im Video.

Datenzugriff und Streaming

0:00 Jetzt ernten wir, was im letzten Modul gesät wurde. Wenn Komponenten auf dem Server laufen, ändert sich der Datenzugriff grundlegend — und zwar in Richtung Einfachheit. Vieles von dem, was in Client-Anwendungen an Zeremonie nötig war, fällt weg: keine Effekte, keine Ladezustände im State, keine Kette von Aufrufen, die aufeinander warten.

0:20 Dafür kommen zwei neue Fragen dazu: Was läuft gleichzeitig, und was darf der Nutzer sehen, bevor alles fertig ist. Am Ende dieses Moduls können Sie ein Dashboard bauen, das sofort erscheint und seine langsamen Teile nachliefert.

Daten in Server Components laden

0:34 Fangen wir mit dem einfachsten Fall an, und der ist tatsächlich einfach. Ich zeige Ihnen gleich eine Komponente, die Daten aus der Datenbank holt und darstellt — in fünf Zeilen, ohne Hook, ohne Zustand. Wenn Sie aus der React- Welt kommen, wird Ihre erste Reaktion sein, dass da etwas fehlt. Es fehlt tatsächlich etwas: die ganze Verwaltung des Ladens, die vorher nötig war.

0:57 In einer Server-Komponente warten Sie einfach auf die Daten. Auf einen Aufruf im Netz, auf die Datenbank, auf irgendeine asynchrone Quelle — und schreiben dann das Ergebnis in die Ausgabe. Es gibt keinen Hook, keinen Zwischenzustand aus Laden, Fehler und Daten, keinen Effekt, der nach dem ersten Rendern startet. Warum geht das?

1:16 Weil diese Komponente nicht im Browser läuft, wo man auf nichts warten darf, sondern auf dem Server, wo Warten der Normalfall ist. Der Server schickt erst los, wenn er fertig ist. Fünf Zeilen, und das Bemerkenswerte ist wieder das Fehlende. Kein Endpunkt, den jemand bauen und absichern muss, kein Aufruf über das Netz, keine Serialisierung und Deserialisierung dazwischen. Die Komponente redet direkt mit der Datenbank.

1:42 Worauf es ankommt: Zugangsdaten und Abfragelogik bleiben dabei vollständig auf dem Server — im Browser landet nur das fertige Ergebnis. Das ist der strukturelle Gewinn dieses Modells. Und es ist zugleich der Punkt, an dem Sorgfalt nötig wird: Wenn der Zugriff so leicht ist, wandert er schnell überallhin. Wir bauen ihm in Modul neun einen festen Ort.

2:04 Die Wasserfall-Kette kennt jeder, der Single-Page-Anwendungen gebaut hat: Die Seite lädt, dann startet ein Effekt, der holt die Daten, dann rendert eine Kindkomponente, deren Effekt die nächsten Daten holt — und so weiter. Jede Stufe kostet einen Umlauf über das Netz. Hier fällt das weg, weil die Abfrage dort steht, wo das Ergebnis gebraucht wird, und weil alles auf demselben Rechner passiert wie die Datenbank.

2:27 Ein netter Nebeneffekt: React fasst identische Aufrufe im selben Baum von sich aus zusammen. Sie dürfen also fragen, wo Sie etwas brauchen. Der erste Punkt ist eine wichtige Änderung gegenüber älterem Next.js: Abfragen werden nicht mehr automatisch zwischengespeichert. Sie blockieren, bis die Antwort da ist. Das klingt nach einem Rückschritt und ist tatsächlich eine Verbesserung — es ist ehrlich. Vorher gab es einen unsichtbaren Cache, der regelmäßig für Verwirrung sorgte.

2:55 Jetzt entscheiden Sie selbst, und wir sehen uns in Modul sechs an, wie. Der dritte Punkt ist ein Reflex, den Sie ablegen sollten: Aus einer Server-Komponente einen eigenen Endpunkt aufzurufen ist ein Umweg über das Netz, der nichts bringt.

Paralleles und sequenzielles Laden

3:10 Jetzt zu der Frage, die über die Hälfte Ihrer Ladezeit entscheidet und die man beim Schreiben leicht übersieht: Läuft das eigentlich nacheinander oder gleichzeitig? Der Unterschied ist im Code winzig — zwei Zeichen, ehrlich gesagt. Die Wirkung ist erheblich. Und die Falle liegt nicht dort, wo die meisten sie vermuten. Zwei Wartezeilen hintereinander bedeuten zwei Wartezeiten hintereinander.

3:33 Das klingt selbstverständlich, sieht im Code aber harmlos aus, weil beide Zeilen untereinander stehen und man sie als Block liest. Wer beide Aufrufe zuerst startet und dann gemeinsam abwartet, halbiert die Zeit. Sequenziell ist nur dann richtig, wenn der zweite Aufruf das Ergebnis des ersten wirklich braucht — wenn Sie also erst den Gast laden müssen, um dessen Buchungen holen zu können.

3:54 In allen anderen Fällen ist es schlicht verschenkte Zeit. Der Kniff steckt in der oberen Hälfte: Die Aufrufe werden gestartet, aber noch nicht abgewartet. Das ist der Punkt, an dem viele straucheln, weil es der Lesegewohnheit widerspricht — man erwartet, dass ein Aufruf erst dann losläuft, wenn man auf ihn wartet. Tatsächlich läuft er los, sobald er aufgerufen wird.

4:16 In unserem Dashboard heißt das konkret: Liegeplätze, offene Rechnungen und Wetterlage haben nichts miteinander zu tun und laufen deshalb gleichzeitig. Aus drei mal zweihundert Millisekunden werden zweihundert. Die letzte Zeile ist die, die Entwarnung gibt und zugleich in die Irre führen kann. Layouts und Seiten rendern von sich aus parallel — dort müssen Sie nichts tun.

4:38 Die Falle sitzt eine Ebene tiefer, innerhalb einer einzelnen Komponente, wo zwei Wartezeilen untereinander stehen. Interessant ist auch die dritte Zeile: Wenn eine von mehreren Abfragen scheitern darf, ohne alles mitzunehmen, brauchen Sie die tolerantere Variante. Für unser Dashboard wäre das die Wetterlage — wenn der Wetterdienst hängt, soll die Belegung trotzdem erscheinen.

5:00 Der zweite Punkt ist der versteckteste und begegnet uns in diesem Modul noch zweimal: Ein Warten auf die Routenparameter ganz oben macht alles Folgende sequenziell. Es sieht aus wie eine harmlose Zeile am Anfang der Komponente und ist in Wahrheit eine Barriere. Der erste Punkt ist wichtig zu wissen, bevor Sie das erste Mal produktiv gehen: Die gebräuchliche Sammelfunktion scheitert vollständig, sobald eine einzige Abfrage scheitert.

5:24 Für unkritische Zusatzdaten ist das die falsche Wahl — dafür gibt es die tolerantere Variante aus der Tabelle.

Daten im Request wiederverwenden

5:31 Jetzt ein kleines Werkzeug mit großer Wirkung — und zwar an einer Stelle, die man zunächst gar nicht mit Datenzugriff verbindet. Es geht um Werte, die an vielen Stellen gebraucht werden, allen voran die Sitzung des angemeldeten Nutzers. Was wir hier einführen, ist gleichzeitig die Grundlage für den Datenzugriffs-Layer in Modul neun und für die ganze Sicherheitsarchitektur in Modul elf.

5:53 React bringt eine Funktion mit, die sich das Ergebnis eines Aufrufs für die Dauer eines Renderdurchgangs merkt. Dieselbe Abfrage an drei Stellen im Baum erzeugt damit eine Datenbankabfrage, nicht drei. Stellen Sie sich einen Portier vor, der sich merkt, wen er heute schon nach dem Ausweis gefragt hat — er fragt nicht bei jeder Tür erneut.

6:12 Wichtig zur Einordnung: Das gilt nur innerhalb einer einzigen Anfrage. Es ist kein Cache im eigentlichen Sinn, sondern ein Kurzzeitgedächtnis für einen Renderdurchgang. Dieses Muster werden Sie im Seminar noch oft sehen, deshalb lohnt sich der Blick. Die Funktion liest das Sitzungs-Cookie und entschlüsselt es — eine Operation, die man nicht zwanzigmal pro Seite machen möchte.

6:34 Mit der Merkung dürfen Sie sie überall aufrufen, wo Sie sie brauchen. Worauf es ankommt, ist die Konsequenz für Ihre Architektur: Sie müssen die Sitzung nicht mehr durch den Komponentenbaum reichen. Und was nicht durchgereicht wird, kann auch nicht versehentlich an der falschen Stelle landen. Genau darauf bauen wir später auf.

6:53 Der erste Punkt ist der eigentliche Grund, warum ich diesem kleinen Werkzeug ein ganzes Kapitel widme. Es ist ein Sicherheitsmuster, das sich als Optimierung tarnt. Wenn die Sitzung überall billig lesbar ist, gibt es keinen Anlass mehr, sie als Eigenschaft weiterzureichen — und damit auch keine Gelegenheit, sie versehentlich an eine Client-Komponente zu übergeben.

7:13 Der zweite Effekt kommt in Modul neun: Weil der Aufruf billig ist, kann jede einzelne Abfrage im Zugriffs-Layer die Berechtigung erneut prüfen, ohne dass es teuer wird. Aus einer Merkfunktion wird so eine Architekturentscheidung. Der erste Punkt grenzt ab, was das Werkzeug nicht ist: Es hält nur für eine Anfrage, nicht darüber hinaus.

7:33 Wer damit echtes Caching zu bauen versucht, ist falsch abgebogen — dafür kommt Modul sechs. Der zweite Punkt ist die häufigste Ursache, wenn es scheinbar nicht wirkt: Unterschiedliche Argumente bedeuten unterschiedliche Ergebnisse, das ist gewollt. Und der dritte kostet die meiste Zeit bei der Fehlersuche: Die Funktion muss außerhalb der Komponente definiert sein.

7:54 Steht sie innen, wird sie bei jedem Rendern neu erzeugt, und die Merkung greift ins Leere.

Streaming mit Suspense

8:00 Jetzt kommt das Werkzeug, mit dem Ihre Anwendung schnell wirkt, auch wenn ein Teil von ihr langsam ist. Der Grundgedanke ist erstaunlich alt und stammt aus dem Fernsehen: Man muss nicht warten, bis der ganze Film übertragen ist, um mit dem Anschauen zu beginnen. Übertragen auf eine Seite heißt das — der schnelle Teil geht sofort raus, der langsame kommt nach.

8:21 Sie umgeben eine langsame Komponente mit einer Suspense-Grenze — daher der Kapitelname — und geben einen Platzhalter an. Next.js schickt dann sofort die fertige Seite mit dem Platzhalter los und liefert den echten Inhalt nach, sobald er da ist. Der Nutzer sieht die Struktur der Seite also, während im Hintergrund noch gearbeitet wird.

8:39 Das ist mehr als ein optischer Trick: Die Verbindung bleibt offen, und der Browser baut den nachgelieferten Teil an der richtigen Stelle ein. Für den Nutzer sieht es aus, als würde die Seite sich selbst vervollständigen. Sehen Sie sich an, was außerhalb der Grenze steht und was innerhalb. Kopfzeile und Belegungszahlen sind schnell und gehen sofort raus.

9:00 Die Saisonstatistik rechnet über Monate und braucht ihre Zeit — sie steht deshalb drin. Der Nutzer bekommt in wenigen Millisekunden eine benutzbare Seite und sieht die Statistik etwas später erscheinen. Worauf es ankommt: Die Grenze zieht man nicht um die Seite, sondern um das langsame Stück. Und je genauer Sie wissen, was langsam ist, desto besser wird das Ergebnis — deshalb lohnt sich Messen vor Optimieren.

9:25 Beides erzeugt einen Ladezustand, der Unterschied ist der Umfang. Die Datei aus Modul drei fasst die ganze Route — sie ist die grobe Klinge und für den Einstieg richtig. Diese Grenze hier fasst genau den Teilbaum, der wartet. Das ist deutlich präziser, und es hat einen zweiten Vorteil, der in Modul drei schon angeklungen ist: Der Platzhalter wandert in die vorgerenderte Hülle und kann damit vorab geladen werden.

9:49 Aus einem Ladezustand wird so ein Baustein für sofortige Navigation. Beides gehört zusammen, auch wenn es zwei Module auseinanderliegt. Der erste Punkt räumt ein Missverständnis aus: Diese Grenze macht eine Komponente nicht dynamisch. Synchrone Arbeit läuft weiterhin beim Vorabbauen, auch innerhalb der Grenze. Sie ist ein Auffangnetz, kein Schalter.

10:10 Der zweite Punkt ist eine Beobachtung aus dem Betrieb: Suchmaschinen und andere Maschinen bekommen die fertige Seite, nicht den Strom — sie brauchen ein vollständiges Dokument. Und der dritte betrifft den Betrieb: Beim Selbsthosten muss der vorgeschaltete Server seine Pufferung abschalten, sonst sammelt er alles und liefert es am Ende gebündelt aus.

10:30 Dazu mehr in Modul dreizehn.

Laufzeit-APIs und ihre Folgen

10:32 Jetzt zu einer Gruppe von Zugriffen, die eine Sonderrolle spielt: Werte, die erst bekannt sind, wenn eine konkrete Anfrage eintrifft. Cookies gehören dazu, die Kopfzeilen der Anfrage, die Suchparameter. Hier hat sich zwischen den Versionen etwas Grundlegendes geändert, und Sie werden im Netz noch viel finden, das den alten Stand beschreibt. Deshalb sehen wir genau hin.

10:55 Cookies, Kopfzeilen, Suchparameter und dynamische Pfadangaben haben eines gemeinsam: Beim Bauen der Anwendung sind sie unbekannt. Erst wenn ein konkreter Nutzer eine konkrete Adresse aufruft, gibt es einen Wert. Komponenten, die darauf zugreifen, können also nicht vorab gerendert werden — sie gehören in eine Suspense-Grenze.

11:15 Tun Sie das nicht, blockieren sie das Vorabrendern der ganzen Route. Next.js sagt Ihnen das inzwischen deutlich, aber es ist gut, den Grund zu kennen statt nur die Meldung. Vier Zugriffe, und die letzte Zeile hat eine Sonderstellung. Bei Pfadangaben gibt es nämlich einen Weg, sie doch schon beim Bauen zu kennen: Sie geben eine Liste der bekannten Werte an, und Next.js baut diese Seiten vorab.

11:39 Für unsere dreihundert Liegeplätze wäre das durchaus sinnvoll — die Nummern stehen ja fest. Für ein Suchergebnis wäre es sinnlos. Merken Sie sich die Unterscheidung: Manche dieser Werte sind grundsätzlich unbekannt, andere nur zufällig. Bei den zufälligen lohnt sich der Blick, ob man sie nicht doch vorab weiß. Das ist der Punkt, an dem ältere Beispiele in die Irre führen.

12:01 Früher zog ein einziger Cookie-Zugriff die ganze Route ins dynamische Rendern — eine Zeile in einer tief liegenden Komponente, und die komplette Seite wurde bei jeder Anfrage neu gebaut. Das war der Grund für viele Verrenkungen. Heute begrenzt die Suspense-Grenze den Schaden auf ihren Teilbaum. Der statische und der gecachte Teil gehen weiterhin sofort raus.

12:23 Nur der personalisierte Teil wartet. Das ist die technische Grundlage dafür, dass Navigationen überhaupt sofort wirken können. Ich muss hier etwas Unangenehmes sagen: Auch die offizielle Dokumentation ist an dieser Stelle nicht durchgängig aktuell. Die Seite mit der Produktions- Checkliste beschreibt noch das alte Verhalten und nennt das heutige Standardrendering experimentell.

12:45 Das ist kein Vorwurf — solche Seiten altern nun einmal — aber Sie sollten es wissen, weil Sie ihr sonst glauben. Prüfen Sie im Zweifel das Änderungsdatum der Seite. Der dritte Punkt ist praktisch: Ein Zugriff in der Metadaten-Erzeugung zählt genauso wie einer in der Seite. Auch die kann eine Route blockieren.

Die statische Hülle maximieren

13:04 Jetzt kommt die Gewohnheit, die ich Ihnen aus diesem Modul am meisten ans Herz lege. Sie ist einfach zu beschreiben, wirkt an vielen Stellen und wird trotzdem selten von Anfang an angewendet. Es geht darum, wo im Komponentenbaum Sie auf etwas warten — und je tiefer das passiert, desto mehr Seite kann Ihre Anwendung sofort ausliefern.

13:23 Stellen Sie sich einen Baum vor, in dem an einer Stelle ein Ast wartet. Alles oberhalb dieser Stelle wartet mit. Wenn Sie also im Layout auf einen Wert warten, warten Navigation, Seitenleiste und der gesamte Inhalt darauf. Warten Sie stattdessen erst in der Komponente, die den Wert wirklich braucht, bleibt der Rest sofort verfügbar.

13:42 Der Ertrag ist unmittelbar sichtbar: Die Hülle, die der Nutzer beim Klicken sieht, wird größer und aussagekräftiger. Es ist dieselbe Menge Arbeit — nur an einer anderen Stelle. Hier sehen Sie das Muster in seiner reinen Form. Die Komponente ist nicht mehr asynchron; sie reicht das Versprechen weiter und lässt eine Kindkomponente darauf warten.

14:03 Der Effekt: Seitenleiste und Inhalt landen in der Hülle, nur der Titel strömt nach. Worauf es ankommt: Am Ergebnis ändert sich nichts. Es wird nichts schneller berechnet, nichts eingespart. Es verschiebt sich allein der Zeitpunkt, zu dem der Nutzer den unbetroffenen Teil sehen darf. Das ist wenig Aufwand für eine spürbare Wirkung.

14:24 Der rote Faden dieser fünf Schritte ist eine Frage: Braucht diese Ebene den Wert wirklich? In den meisten Fällen lautet die Antwort nein — er wurde nur dort gelesen, weil es sich beim Schreiben angeboten hat. Deshalb steht Schritt zwei im Zentrum. Erst danach entscheiden Sie zwischen den beiden Auswegen: verschieben und in eine Suspense-Grenze fassen, oder cachen, wenn der Wert gar nicht anfrageabhängig ist.

14:47 Und der erste Schritt ist der bequemste: Next.js nennt Ihnen Route und Zeile. Sie müssen nicht suchen, nur lesen. Der erste Punkt beschreibt den schlimmsten Fall und zugleich den häufigsten Anfängerfehler: ein Warten im Wurzel-Layout. Das trifft jede einzelne Seite der Anwendung, und niemand sieht es der Seite an. Der zweite Punkt nennt den üblichen Auslöser — Sitzungsdaten in der Kopfzeile.

15:11 Das ist so verbreitet, weil es fachlich vollkommen richtig ist: Das Benutzermenü gehört nach oben. Nur der Zugriff gehört nicht dorthin. Und der dritte Punkt beruhigt: Sie ändern damit kein Verhalten, nur den Zeitpunkt. Es ist eine Umstellung ohne fachliches Risiko.

Datenzugriff aus dem Client

15:28 Zum Abschluss die ehrliche Gegenprobe: Es gibt Fälle, in denen der Server nicht der richtige Ort ist. Das ganze Modul hat vom Serverzugriff gehandelt, und ich möchte nicht den Eindruck hinterlassen, dass damit alles erledigt wäre. Sehen wir uns an, welche Fälle das sind und wie man sie sauber löst. Manches gehört in den Browser: eine Liste, die beim Scrollen nachlädt, ein Suchfeld mit Vorschlägen während des Tippens, eine Anzeige, die sich alle paar Sekunden aktualisiert.

15:55 Diese Fälle haben eines gemeinsam — sie werden durch eine Handlung des Nutzers ausgelöst, nicht durch den Aufbau der Seite. React bietet dafür eine Funktion, mit der eine Client-Komponente auf ein Versprechen wartet, das der Server gestartet hat. Und für die aufwendigeren Fälle nennt die Dokumentation zwei etablierte Bibliotheken.

16:15 Dieses Muster ist eleganter, als es zunächst wirkt. Der Server startet die Abfrage, wartet aber nicht darauf, sondern reicht das Versprechen weiter. Die Client-Komponente wartet dann darauf. Der Gewinn: Die Abfrage läuft bereits, während die Seite noch übertragen wird — es entsteht kein zweiter Umlauf über das Netz, wie ihn ein Effekt im Browser erzeugt hätte.

16:36 Worauf es ankommt: Diese Konstruktion braucht eine Suspense-Grenze darum. Ohne sie hätte der Browser nichts zu zeigen, während er wartet. Die letzte Zeile ist die, die man in Reviews am häufigsten korrigiert. Wenn eine Liste einmal geladen und danach nur noch gefiltert wird, gehören Laden und Filtern an verschiedene Orte: Laden auf den Server, Filtern in den Browser.

16:59 Sehr oft sieht man stattdessen beides im Browser — die Liste wird nachgeladen, weil der Filter ja auch dort ist. Damit verschenkt man alles, was dieses Modul aufgebaut hat. Die Faustregel ist einfach: Was beim Rendern feststeht, gehört auf den Server. Was auf eine Handlung reagiert, in den Browser.

Modul 5 zusammengefasst

17:17 Vier Dinge zum Mitnehmen. In Server-Komponenten wird gewartet, nicht gehookt. Unabhängige Abfragen starten gemeinsam. Die Suspense-Grenze begrenzt die Wartezeit auf den Teilbaum, der sie verursacht. Und der Zugriff gehört so tief wie möglich — davon lebt die Hülle, die Ihre Navigation sofort wirken lässt. Im nächsten Modul beantworten wir die Frage, die hier mehrfach angeklungen ist: Was wird eigentlich gecacht und wodurch fällt es wieder?

17:43 Das Modell dafür hat sich grundlegend geändert, und ich halte die Änderung für eine der besseren.

Lieber mit Trainer? Dieses Modul ist Teil unserer Team-Schulungen — mit Übungen, Ihrem eigenen Code und Fragen, die ein Video nicht beantwortet. Mehr erfahren →