Transcript

00:00:00(fröhliche Musik) - Okay, hallo zusammen.
00:00:06Mein Name ist Aurora.
00:00:07Ich bin Webentwicklerin aus Norwegen.
00:00:09Ich arbeite als Beraterin bei Crane Consulting und entwickle aktiv mit dem Next.js App Router in meinem aktuellen Beratungsprojekt.
00:00:16Heute zeige ich Ihnen Muster für Komposition,
00:00:18Caching und Architektur in modernem Next.js,
00:00:21die Ihnen helfen,
00:00:22Skalierbarkeit und Leistung zu gewährleisten.
00:00:24Lassen Sie mich zunächst das grundlegendste Konzept für diesen Vortrag auffrischen: statisches und dynamisches Rendering.
00:00:30Wir sind beiden im Next.js App Router begegnet.
00:00:33Statisches Rendering ermöglicht uns den Bau schnellerer Websites,
00:00:36da vorgerenderte Inhalte zwischengespeichert und global verteilt werden können,
00:00:39sodass Benutzer schneller darauf zugreifen können.
00:00:42Zum Beispiel die Next.js Conf-Website.
00:00:46Statisches Rendering reduziert die Serverlast,
00:00:48da Inhalte nicht für jede Benutzeranfrage neu generiert werden müssen.
00:00:51Vorgerenderte Inhalte sind auch für Suchmaschinen-Crawler leichter zu indizieren,
00:00:55da die Inhalte bereits beim Laden der Seite verfügbar sind.
00:00:58Dynamisches Rendering hingegen ermöglicht unserer Anwendung,
00:01:02Echtzeit- oder häufig aktualisierte Daten anzuzeigen.
00:01:05Es ermöglicht uns auch,
00:01:06personalisierte Inhalte wie Dashboards und Benutzerprofile bereitzustellen.
00:01:09Zum Beispiel das Vercel-Dashboard.
00:01:12Mit dynamischem Rendering können wir auf Informationen zugreifen,
00:01:15die nur zur Anfragezeit bekannt sein können.
00:01:16In diesem Fall,
00:01:17welcher Benutzer auf sein Dashboard zugreift,
00:01:19nämlich ich.
00:01:20Es gibt bestimmte APIs,
00:01:21die dazu führen können,
00:01:22dass eine Seite dynamisch gerendert wird.
00:01:25Die Verwendung der `params`- und `search params`-Props,
00:01:27die an Seiten oder deren äquivalente Hooks übergeben werden,
00:01:30führt zu dynamischem Rendering.
00:01:32Bei `params` können wir jedoch eine Reihe vorgerenderter Seiten mithilfe generischer statischer `params` vordefinieren und die Seiten auch zwischenspeichern,
00:01:38während sie von Benutzern generiert werden.
00:01:40Darüber hinaus führt das Lesen eingehender Request-Cookies und -Header dazu,
00:01:44dass die Seite dynamisch gerendert wird.
00:01:46Im Gegensatz zu `params` führt der Versuch,
00:01:48etwas mithilfe von Headern oder Cookies zwischenzuspeichern oder vorzurendern,
00:01:51jedoch zu Fehlern während des Builds,
00:01:52da diese Informationen nicht im Voraus bekannt sein können.
00:01:56Schließlich erzwingt die Verwendung von `fetch` mit einer `data cache configuration no store` ebenfalls dynamisches Rendering.
00:02:00Das sind also die wenigen – es gibt noch ein paar weitere APIs,
00:02:03die dynamisches Rendering verursachen können,
00:02:04aber das sind die,
00:02:05denen wir am häufigsten begegnen.
00:02:06In früheren Next-Versionen wurde eine Seite entweder vollständig statisch oder vollständig dynamisch gerendert.
00:02:13Eine einzige dynamische API auf einer Seite führt dazu,
00:02:15dass die gesamte Seite dynamisch gerendert wird.
00:02:17Zum Beispiel eine einfache Authentifizierungsprüfung für den Wert eines Cookies.
00:02:20Durch die Nutzung von React-Serverkomponenten mit Suspense können wir dynamische Inhalte wie ein personalisiertes Willkommensbanner oder Empfehlungen streamen,
00:02:27sobald sie bereit sind,
00:02:29und nur Fallbacks mit Suspense bereitstellen,
00:02:31während statische Inhalte wie ein Newsletter angezeigt werden.
00:02:34Sobald wir jedoch mehrere asynchrone Komponenten auf einer dynamischen Seite hinzufügen,
00:02:38wie z.B.
00:02:39ein Feature-Produkt,
00:02:40würden diese ebenfalls zur Anfragezeit ausgeführt,
00:02:42obwohl sie nicht von dynamischen APIs abhingen..
00:02:45Um also das anfängliche Laden der Seite nicht zu blockieren,
00:02:47würden wir diese Komponenten ebenfalls suspendieren und streamen,
00:02:50was zusätzlichen Aufwand bedeutet,
00:02:52wie das Erstellen von Skeletons und das Sorgen um Dinge wie Layout-Verschiebungen.
00:02:56Seiten sind jedoch oft eine Mischung aus statischen und dynamischen Inhalten.
00:03:01Zum Beispiel eine E-Commerce-App,
00:03:03die von Benutzerinformationen abhängt,
00:03:05aber größtenteils statische Daten enthält.
00:03:07Die erzwungene Wahl zwischen statisch oder dynamisch führt zu viel redundanter Verarbeitung auf dem Server für Inhalte,
00:03:14die sich nie oder sehr selten ändern,
00:03:17und ist nicht optimal für die Leistung.
00:03:19Um dieses Problem zu lösen,
00:03:21wurde auf der letztjährigen Next.js Conf die `use cache`-Direktive angekündigt.
00:03:26Und dieses Jahr,
00:03:27wie wir in der Keynote gesehen haben,
00:03:28ist sie in Next.js 16 verfügbar.
00:03:30Mit `use cache` werden Seiten also nicht mehr gezwungen,
00:03:33entweder statisch oder dynamisch gerendert zu werden.
00:03:36Sie können beides sein.
00:03:37Und Next.js muss nicht mehr raten,
00:03:39was eine Seite ist,
00:03:40basierend darauf,
00:03:41ob sie auf Dinge wie `params` zugreift.
00:03:43Alles ist standardmäßig dynamisch,
00:03:44und `use cache` ermöglicht es uns,
00:03:46explizit Caching zu aktivieren.
00:03:47`use cache` ermöglicht komponierbares Caching.
00:03:51Wir können entweder eine Seite,
00:03:53eine React-Komponente oder eine Funktion als cachebar markieren.
00:03:55Hier können wir die Feature-Produkte-Komponente tatsächlich zwischenspeichern,
00:03:59da sie keine Anfrage und Verarbeitung benötigt und keine dynamischen APIs verwendet.
00:04:03Und diese Cache-Segmente können weiter vorgerendert und als Teil der statischen Shell mit partiellem Pre-Rendering integriert werden,
00:04:09was bedeutet,
00:04:10dass die Feature-Produkte jetzt beim Laden der Seite verfügbar sind und nicht gestreamt werden müssen.
00:04:14Nachdem wir nun dieses wichtige Hintergrundwissen haben,
00:04:18machen wir eine Demo.
00:04:19Eine Verbesserung einer Codebasis mit häufig auftretenden Problemen in Next.js-Apps.
00:04:24Dazu gehören tiefes Prop-Drilling,
00:04:25das die Wartung und Refaktorierung von Features erschwert,
00:04:27redundantes clientseitiges JavaScript und große Komponenten mit mehreren Verantwortlichkeiten sowie das Fehlen von statischem Rendering,
00:04:33was zu zusätzlichen Serverkosten und einer schlechteren Leistung führt.
00:04:36Also, fangen wir an.
00:04:37Und geben Sie mir eine Sekunde hier.
00:04:50Alles klar, super.
00:04:54Das ist also eine sehr einfache Anwendung.
00:04:56Sie ist von einer E-Commerce-Plattform inspiriert.
00:04:59Und lassen Sie mich hier eine erste Demo machen.
00:05:01Ich kann diese Seite also laden.
00:05:03Ich habe Inhalte wie dieses Feature-Produkt.
00:05:06Ich habe Feature-Kategorien, verschiedene Produktdaten.
00:05:09Es gibt auch diese 'Alle durchsuchen'-Seite hier,
00:05:13auf der ich alle Produkte auf der Plattform sehen und zwischen ihnen blättern kann.
00:05:20Dann haben wir hier diese 'Über uns'-Seite,
00:05:22die einfach statisch ist.
00:05:24Ich kann mich auch als Benutzer anmelden.
00:05:27Und das meldet mich bei meinem Benutzer an.
00:05:30Und erhalte dann auch personalisierte Inhalte auf meinem Dashboard hier.
00:05:33Wie zum Beispiel empfohlene Produkte oder diese personalisierten Rabatte hier.
00:05:38Beachten Sie hier, es gibt eine ziemlich gute Mischung.
00:05:42Oh, noch eine Seite, die ich vergessen habe zu zeigen.
00:05:45Die Produktseite, die wichtigste.
00:05:47Auch hier können wir Produktinformationen sehen und sie dann bei Bedarf für unseren Benutzer speichern.
00:05:52Beachten Sie also,
00:05:53dass es in dieser App eine ziemlich gute Mischung aus statischen und dynamischen Inhalten gibt,
00:05:57aufgrund all unserer benutzerabhängigen Funktionen.
00:05:59Werfen wir auch einen Blick auf den Code, der hier wäre.
00:06:05Ich verwende hier natürlich den App Router in Next.js 16.
00:06:08Ich habe alle meine verschiedenen Seiten,
00:06:10wie die 'Über uns'-Seite,
00:06:11die 'Alle'-Seite,
00:06:12unsere Produktseite.
00:06:13Ich habe auch – ich verwende hier Feature Slicing,
00:06:15um meinen App-Ordner sauber zu halten.
00:06:17Ich habe verschiedene Komponenten und Abfragen,
00:06:20die mit meiner Datenbank über Prisma kommunizieren.
00:06:23Also ja, und ich habe das alles absichtlich verlangsamt.
00:06:25Deshalb haben wir diese wirklich lange Ladephase,
00:06:28nur damit wir leichter sehen können,
00:06:30was passiert.
00:06:31Die häufigen Probleme,
00:06:32an denen wir hier arbeiten wollten und die wir tatsächlich in dieser Anwendung haben,
00:06:36waren Prop-Drilling,
00:06:36das die Wartung und Refaktorierung von Features erschwert,
00:06:39übermäßiges clientseitiges JavaScript und das Fehlen von statischem Rendering,
00:06:43was zu zusätzlichen Serverkosten und einer schlechteren Leistung führt.
00:06:47Das Ziel dieser Demo ist es also im Grunde,
00:06:49diese App mit einigen cleveren Mustern bezüglich Komposition,
00:06:53Caching und Architektur zu verbessern,
00:06:55um diese häufigen Probleme zu beheben und sie schneller,
00:06:58skalierbarer und einfacher zu warten.
00:07:01Fangen wir damit an.
00:07:02Das erste Problem,
00:07:03das wir beheben wollen,
00:07:04hängt tatsächlich mit Prop-Drilling zusammen.
00:07:05Und das wäre hier auf der Seite.
00:07:10Beachten Sie hier,
00:07:11ich habe diese `loggedIn`-Variable ganz oben.
00:07:15Und Sie sehen, ich übergebe sie an ein paar Komponenten.
00:07:17Sie wurde tatsächlich über mehrere Ebenen bis in dieses persönliche Banner weitergegeben.
00:07:20Das wird es also schwierig machen,
00:07:22Dinge hier wiederzuverwenden,
00:07:23weil wir immer diese `loggedIn`-Abhängigkeit für unser Willkommensbanner haben.
00:07:28Bei Serverkomponenten wäre es die beste Praxis,
00:07:30das Datenabrufen tatsächlich in die Komponenten zu verschieben,
00:07:34die dies verwenden,
00:07:35und Promises tiefer im Baum aufzulösen.
00:07:37Und damit dies als authentifiziert gilt,
00:07:39solange es entweder `fetch` oder etwas wie React Cache verwendet,
00:07:43können wir mehrere Aufrufe davon duplizieren und es einfach überall in unseren Komponenten wiederverwenden.
00:07:48Das wäre also völlig in Ordnung, es wiederzuverwenden.
00:07:51Jetzt können wir dies also tatsächlich in den personalisierten Bereich hier verschieben.
00:07:54Und wir werden diese Prop nicht mehr benötigen.
00:07:57Und es einfach direkt – hoppla – hier einfügen.
00:08:01Und wir müssen dies nicht mehr übergeben.
00:08:04Und da wir diesen asynchronen Aufruf nun in den personalisierten Bereich verschieben,
00:08:07blockieren wir die Seite nicht mehr.
00:08:09Wir können dies einfach mit einem einfachen Suspense hier suspendieren.
00:08:13Und wir werden diesen Fallback nicht benötigen.
00:08:16Was das Willkommensbanner betrifft,
00:08:19so werden wir wohl dasselbe tun.
00:08:22Aber zu versuchen,
00:08:23die `loggedIn`-Variable oder den Wert hier zu verwenden,
00:08:26funktioniert nicht,
00:08:27oder?
00:08:27Weil dies eine Client-Komponente ist.
00:08:29Wir müssen das also anders lösen.
00:08:30Und wir werden hier ein ziemlich cleveres Muster verwenden,
00:08:33um dies zu lösen.
00:08:33Wir werden tatsächlich ins Layout gehen und hier alles mit einem Auth-Provider umwickeln.
00:08:39Ich werde dies also einfach um meine gesamte App hier legen und diese `loggedIn`-Variable hierher holen.
00:08:45Und ich möchte definitiv nicht mein gesamtes Root-Layout blockieren.
00:08:48Lassen Sie uns hier das `await` entfernen.
00:08:50Und dies einfach als Promise an diesen Auth-Provider weitergeben.
00:08:55Und dies kann einfach diese Promise enthalten.
00:08:57Es kann einfach dort warten,
00:08:59bis wir bereit sind,
00:09:00es zu lesen.
00:09:01Das haben wir jetzt also eingerichtet.
00:09:03Das bedeutet,
00:09:04wir können tatsächlich diese Prop zuerst loswerden.
00:09:09Und wir werden diese,
00:09:10die zum persönlichen Banner durchdringt,
00:09:12loswerden.
00:09:12Und wir werden das Prop-Drilling auch hier oder die Signatur loswerden.
00:09:16Und jetzt können wir diesen Auth-Provider verwenden,
00:09:19um diesen `loggedIn`-Wert lokal innerhalb des persönlichen Banners mit `useAuth` mit dem gerade erstellten Provider abzurufen.
00:09:26Und es mit `use` lesen.
00:09:28Das wird also tatsächlich so funktionieren,
00:09:30dass wir dies suspendieren müssen,
00:09:32während es aufgelöst wird.
00:09:33Ich habe also jetzt diesen kleinen Datenabruf im persönlichen Banner ko-lokalisiert.
00:09:37Und ich muss diese Props nicht mehr herumreichen.
00:09:40Und während dies aufgelöst wird,
00:09:41lassen Sie uns dies auch mit einem Fallback suspendieren.
00:09:44Und lassen Sie uns hier einfach ein allgemeines Banner verwenden,
00:09:48um ungewöhnliche kumulative Verschiebungen zu vermeiden.
00:09:51Und schließlich auch dieses loswerden.
00:09:53Dieses Willkommensbanner ist jetzt also komponierbar.
00:09:58Es ist wiederverwendbar.
00:09:59Wir haben keine seltsamen Props oder Abhängigkeiten auf der Startseite.
00:10:02Und da wir dies so einfach wiederverwenden können,
00:10:05lassen Sie uns es tatsächlich auch zu dieser Browser-Seite hier hinzufügen,
00:10:10die hier sein wird.
00:10:11Und ich kann es einfach hier ohne Abhängigkeiten verwenden.
00:10:15Durch diese Muster können wir eine gute Komponentenarchitektur unter Verwendung von React Cache und React Use aufrechterhalten und unsere Komponenten nutzbarer und komponierbarer machen.
00:10:30Alles klar.
00:10:31Kommen wir zur nächsten häufigen Herausforderung: übermäßiges clientseitiges JavaScript und große Komponenten mit mehreren Verantwortlichkeiten.
00:10:40Tatsächlich ist das auch auf der 'Alle'-Seite hier.
00:10:43Und wieder müssen wir an diesem Willkommensbanner arbeiten.
00:10:46Es ist derzeit eine Client-Komponente.
00:10:48Und der Grund,
00:10:48warum es eine Client-Komponente ist,
00:10:50ist,
00:10:51dass ich hier diesen sehr einfachen 'entlassen'-Zustand habe.
00:10:53Ich kann einfach darauf klicken.
00:10:54Es ist eine schöne UI-Interaktion.
00:10:56Das ist in Ordnung.
00:10:57Was jedoch nicht so gut ist,
00:10:58ist,
00:10:59dass ich diese gesamte Komponente deswegen in eine clientseitige Komponente oder eine Client-Komponente umwandle.
00:11:04Und ich verwende sogar SWR für clientseitiges Abrufen.
00:11:07Ich habe jetzt diese API-Schicht hier.
00:11:08Ich habe keine Typsicherheit mehr in meinen Daten.
00:11:11Ja, das ist nicht notwendig.
00:11:12Und wir verletzen hier auch die Trennung der Belange,
00:11:15weil wir UI-Logik mit Daten vermischen.
00:11:18Also,
00:11:18lassen Sie uns ein weiteres cleveres Muster verwenden,
00:11:20um dies zu beheben.
00:11:21Es wird das Donut-Muster genannt.
00:11:23Im Grunde werde ich dies in einen clientseitigen Wrapper extrahieren.
00:11:27Also, erstellen wir hier eine neue Komponente.
00:11:29Und nennen wir es `BannerContainer`.
00:11:32Und dies wird unsere interaktive Logik mit der `use client`-Direktive enthalten.
00:11:37Wir können die Signatur erstellen.
00:11:38Wir können alles einfügen, was wir gerade hatten.
00:11:42Und anstatt diese Banner zu verwenden,
00:11:44werde ich hier einfach eine Prop einfügen,
00:11:46die die Children sein werden.
00:11:48Deshalb wird es das Donut-Muster genannt.
00:11:50Wir erstellen einfach diese Wrapper-UI-Logik um serverseitig gerenderte Inhalte,
00:11:54oder es könnten serverseitig gerenderte Inhalte sein.
00:11:56Und da wir diese clientseitige Abhängigkeit nicht mehr haben,
00:11:59können wir `use client` entfernen.
00:12:01Wir können stattdessen unsere asynchrone `isAuth`-Funktion hier verwenden.
00:12:06Wir können dies zu einer asynchronen Serverkomponente machen.
00:12:09Wir können sogar clientseitiges Abrufen durch serverseitiges Abrufen ersetzen.
00:12:11Also,
00:12:12lassen Sie mich einfach die Rabattdaten direkt hier abrufen.
00:12:16Rabattdaten.
00:12:18Und einfach unser reguläres mentales Modell wie zuvor mit Typsicherheit nutzen.
00:12:24Und das bedeutet,
00:12:24ich kann auch diese API-Schicht löschen,
00:12:26mit der ich sowieso nicht arbeiten möchte.
00:12:29Schließlich können wir für `isLoading` einfach ein neues Willkommensbanner hier mit unserem Donut-Muster-Banner-Container exportieren,
00:12:35der serverseitig gerenderte Inhalte enthält.
00:12:38Und das bedeutet, wir brauchen `isLoading` nicht mehr.
00:12:40Wir haben also im Grunde das Ganze in eine Serverkomponente refaktorisiert und einen UI-Logikpunkt extrahiert.
00:12:46Aber was ist das?
00:12:48Es sieht so aus, als hätte ich einen weiteren Fehler.
00:12:51Das liegt tatsächlich an Motion.
00:12:53Verwenden Sie Motion.
00:12:54Es ist eine wirklich großartige Animationsbibliothek,
00:12:57aber sie erfordert die `useClient`-Direktive.
00:12:59Und wieder müssen wir dies nicht nur für Animationen zu `useClient` machen.
00:13:03Wir können wieder einen Donut-Muster-Wrapper erstellen und einfach Wrapper für diese Animationen extrahieren.
00:13:10Und das bedeutet,
00:13:11wir müssen hier nichts in clientseitig umwandeln.
00:13:14Und ich vermisse wahrscheinlich etwas hier unten.
00:13:17Ja.
00:13:18Da haben wir's.
00:13:21Jetzt wurde hier also alles auf Server umgestellt.
00:13:23Wir haben die gleiche Interaktion.
00:13:24Wir haben immer noch unsere interaktive Logik hier,
00:13:27aber jetzt haben wir diese eine Möglichkeit,
00:13:28Daten abzurufen.
00:13:29Und wir haben viel weniger clientseitiges JS.
00:13:31Tatsächlich verwende ich dieses Donut-Muster selbst für diesen UI-Boundary-Helfer,
00:13:40der so aussieht.
00:13:42Sehen Sie das?
00:13:43Das zeigt also wieder, was ich meine, oder?
00:13:45Mit dem Donut-Muster haben wir diese Client-Komponente um eine Serverkomponente herum.
00:13:49Ich habe auch viele meiner anderen Komponenten mit diesem UI-Helfer hier markiert.
00:13:53Auch hier habe ich weitere Serverkomponenten.
00:13:56Lassen Sie uns diese auch verbessern,
00:13:58da wir mittlerweile ziemlich gut darin sind.
00:14:01Sie sind im Footer.
00:14:04Diese Kategorien – ich meine,
00:14:05ich habe diese schöne Komponente,
00:14:07die ihre eigenen Daten abruft.
00:14:08Und ich wollte nur diese `showMore`-Funktion hinzufügen,
00:14:11nur für den Fall,
00:14:12dass es wirklich lang wird.
00:14:14Und mit dem Donut-Muster kann ich hier einfach eine `ShowMore`-Komponente umwickeln.
00:14:20Und dies wird meine UI-Logik enthalten.
00:14:23Und es sieht so aus, oder?
00:14:27Ziemlich cool.
00:14:28Und dies enthält nun die Client-Logik,
00:14:30die es uns ermöglicht,
00:14:31State zu verwenden.
00:14:33Wir verwenden die `children count` und `toArray`,
00:14:35um dies zu schneiden.
00:14:36Und das Coole hier ist,
00:14:37dass diese beiden jetzt vollständig komponierbare,
00:14:39wiederverwendbare Komponenten sind,
00:14:41die so zusammenarbeiten.
00:14:42Das ist also wirklich die Schönheit dieser Muster,
00:14:44die wir hier lernen.
00:14:45Sie können dies für alles verwenden.
00:14:50Ich verwende es auch für dieses Modal hier.
00:14:52Ja,
00:14:52denken Sie einfach daran,
00:14:54wenn Sie das nächste Mal erwägen,
00:14:55irgendeine Art von Client-Logik zu Ihren Serverkomponenten hinzuzufügen.
00:14:59Okay, wir kennen das Donut-Muster.
00:15:01Wir wissen,
00:15:01wie man es nutzt,
00:15:02um diese komponierbaren Komponenten zu erstellen und clientseitiges JS zu vermeiden,
00:15:07sodass wir zum letzten Problem übergehen können.
00:15:10Lassen Sie mich das noch einmal schließen.
00:15:13Das wäre also der Mangel an statischen Rendering-Strategien,
00:15:18richtig?
00:15:18Wenn ich mir meine Build-Ausgabe ansehe,
00:15:20habe ich tatsächlich jede einzelne Seite als dynamische Seite hier.
00:15:24Das bedeutet also,
00:15:25dass jedes Mal,
00:15:25wenn ich hier etwas lade,
00:15:26dies für jeden einzelnen Benutzer ausgeführt wird.
00:15:29Entschuldigung.
00:15:30Jeder einzelne Benutzer,
00:15:31der dies öffnet,
00:15:31wird diesen Ladezustand erhalten.
00:15:33Das wird Serverkosten verschwenden und die Leistung verschlechtern.
00:15:37Und das bedeutet auch,
00:15:38dass etwas in meinen Seiten dynamisches Rendering verursacht oder dynamisches Rendering für alle meine Seiten erzwingt.
00:15:45Tatsächlich ist es in meinem Root-Layout.
00:15:49Ich weiß nicht, ob Sie das erlebt haben.
00:15:51Es ist hier drüben.
00:15:53In meinem Header habe ich dieses Benutzerprofil.
00:15:57Und dies verwendet natürlich Cookies,
00:15:58um den aktuellen Benutzer abzurufen,
00:16:00und das bedeutet,
00:16:00dass alles andere auch dynamisch gerendert wird.
00:16:02Denn noch einmal,
00:16:03Seiten können entweder dynamisch oder statisch sein,
00:16:06richtig?
00:16:06Dies ist ein ziemlich häufiges Problem und etwas,
00:16:09das in früheren Next-Versionen bereits gelöst wurde,
00:16:11also schauen wir mal,
00:16:12was wir tun könnten.
00:16:13Eine Sache,
00:16:14die wir tun könnten,
00:16:15ist,
00:16:15eine Routengruppe zu erstellen und unsere App in statische und dynamische Abschnitte aufzuteilen,
00:16:20was es mir ermöglichen würde,
00:16:21meine 'Über uns'-Seite zu extrahieren.
00:16:23Ich könnte dies statisch rendern.
00:16:25Für einige Apps ist das in Ordnung,
00:16:27aber in meinem Fall ist die wichtige Seite die Produktseite,
00:16:30und diese ist immer noch dynamisch,
00:16:31also nicht wirklich hilfreich.
00:16:33Wie wäre es mit dieser Strategie?
00:16:35Hier erstelle ich also diesen Request-Kontext-Parameter,
00:16:38der einen bestimmten Zustand in meine URL kodiert,
00:16:40und dann kann ich `generate static params` verwenden,
00:16:43um alle verschiedenen Varianten meiner Seiten zu generieren.
00:16:46Das würde tatsächlich,
00:16:47kombiniert mit clientseitigem Abrufen der Benutzerdaten,
00:16:50es mir ermöglichen,
00:16:51dies auf meiner Produktseite zwischenzuspeichern.
00:16:54Definitiv ein praktikables Muster.
00:16:55Es wird vom Vercel Flags SDK empfohlen,
00:16:58ich glaube,
00:16:58es heißt Precompute-Muster.
00:17:00Aber das ist wirklich komplex,
00:17:01und ich habe mehrere Möglichkeiten,
00:17:03Daten abzurufen.
00:17:04Und eigentlich möchte ich meine ganze App nicht darauf umschreiben.
00:17:07Was wäre also,
00:17:07wenn wir keine dieser Workarounds machen müssten?
00:17:10Was wäre, wenn es einen einfacheren Weg gäbe?
00:17:12Nun, den gibt es.
00:17:14Kehren wir zurück zu unserer Anwendung.
00:17:17Wir können also tatsächlich zur Next-Konfiguration gehen und einfach Cache-Komponenten aktivieren.
00:17:23Oh, schön.
00:17:25Okay,
00:17:25und was dies tut,
00:17:26wie Sie aus der Keynote wissen,
00:17:28wird tatsächlich alle unsere asynchronen Aufrufe zur Anfragezeit oder dynamisch machen.
00:17:34Und es wird uns auch Fehler geben,
00:17:36wann immer wir einen asynchronen Aufruf nicht suspendiert haben,
00:17:39und es wird uns diese `use cache`-Direktive geben,
00:17:42die wir verwenden können,
00:17:43um granular entweder eine Seite,
00:17:45eine Funktion oder eine Komponente zwischenzuspeichern.
00:17:48Also ja, lassen Sie uns dies nutzen.
00:17:51Wir können hier mit der Startseite beginnen.
00:17:55Werfen wir einen Blick darauf.
00:17:56Also wieder habe ich diese Mischung aus statischen und dynamischen Inhalten.
00:17:59Ich habe mein Willkommensbanner für mich,
00:18:01etwas für Sie,
00:18:02auch für mich.
00:18:03Schauen wir uns das noch einmal mit diesem UI-Helfer an.
00:18:06Zum Beispiel wird das Banner hier dynamisch gerendert.
00:18:10Während ich dies als Hybrid-Rendering markiert habe,
00:18:14weil der Hero dieses asynchrone Ding abruft und es ziemlich langsam ist.
00:18:18Aber es hängt nicht von Benutzerdaten oder dynamischen APIs ab.
00:18:21Das bedeutet also,
00:18:22dass alles,
00:18:23was hier hybrid gerendert wird,
00:18:24tatsächlich über Anfragen und Benutzer hinweg wiederverwendet werden kann.
00:18:27Und wir können die `use cache`-Direktive dafür verwenden.
00:18:30Also,
00:18:30fügen wir hier die `use cache`-Direktive hinzu und markieren dies als gecacht.
00:18:35Und das wird es mir ermöglichen – wann immer ich diese Seite neu lade – ich habe das nicht gespeichert.
00:18:43Da haben wir's.
00:18:44Dieser Teil wird nicht neu geladen, weil er gecacht ist.
00:18:47Es ist jetzt statisch, richtig?
00:18:49Und es gibt auch andere verwandte APIs wie den Cache-Tag,
00:18:53der es mir ermöglicht,
00:18:54dies zu typisieren oder den spezifischen Cache-Eintrag granular zu validieren oder meine Offenbarungsperiode zu definieren.
00:19:01Aber für diese Demo konzentrieren wir uns einfach auf die einfache Direktive.
00:19:05Nachdem ich nun diese `use cache`-Direktive habe,
00:19:07kann ich tatsächlich meine Suspense-Grenze um diesen Hero entfernen.
00:19:10Und das bedeutet – nun,
00:19:12was dies bewirken wird,
00:19:13ist,
00:19:14dass partielles Pre-Rendering dies tatsächlich in die statisch vorgerenderte Shell aufnehmen kann,
00:19:19sodass dieser Hero in diesem Fall ein Teil meiner Build-Ausgabe sein wird.
00:19:23Machen wir dasselbe für alles andere auf dieser Seite,
00:19:27das geteilt werden kann.
00:19:28Zum Beispiel habe ich hier diese Feature-Kategorien.
00:19:31Lassen Sie uns dort dasselbe tun.
00:19:33Und die `use cache`-Direktive hinzufügen und dies als gecacht markieren.
00:19:37So.
00:19:39Und wir können die Suspense-Grenze entfernen.
00:19:40Wir werden dies nicht mehr benötigen.
00:19:43Dasselbe gilt für die Feature-Produkte.
00:19:44Fügen wir `use cache` hinzu und markieren dies als gecacht.
00:19:48Hoppla.
00:19:50Und dann die Suspense-Grenze entfernen.
00:19:52Beachten Sie also,
00:19:53wie viel Komplexität ich hier einfach entfernen kann.
00:19:55Ich muss mir keine Sorgen mehr um meine Skeletons,
00:19:57meine kumulative Layout-Verschiebung machen,
00:19:59die ich zuvor hatte.
00:20:00Und die Seite ist nicht mehr – oder wir haben diese seitenweite statische versus dynamische Einschränkung nicht mehr.
00:20:07Wenn ich diese Seite jetzt lade,
00:20:10sehen Sie,
00:20:10dass hier alles gecacht ist,
00:20:12außer diesem wirklich benutzerspezifischen Inhalt.
00:20:16Richtig.
00:20:18Das ist also ziemlich cool.
00:20:19Gehen wir zur 'Durchsuchen'-Seite und machen dort dasselbe.
00:20:24Ja.
00:20:25Ich habe hier bereits alle meine Grenzen markiert,
00:20:27damit Sie leicht verstehen können,
00:20:28was passiert.
00:20:29Und ich möchte zumindest diese Kategorien zwischenspeichern.
00:20:33Es sieht jedoch so aus, als würde ich einen Fehler bekommen.
00:20:37Vielleicht erkennen Sie das.
00:20:38Das bedeutet also, ich habe eine blockierende Route.
00:20:40Und ich verwende keine Suspense-Grenze,
00:20:42obwohl ich es sollte.
00:20:43Das Aktualisieren zeigt, es stimmt, oder?
00:20:46Das ist wirklich langsam.
00:20:47Und es verursacht Leistungsprobleme und eine schlechte UX.
00:20:50Das ist also großartig.
00:20:51`use cache` oder Cache-Komponenten helfen mir,
00:20:53meine blockierenden Routen zu identifizieren.
00:20:55Schauen wir uns tatsächlich an, was darin passiert.
00:20:57Das ist also das Problem, richtig?
00:20:59Ich rufe diese Kategorien auf oberster Ebene ab und habe keine Suspense-Grenze darüber.
00:21:03Im Grunde müssen wir eine Wahl treffen.
00:21:05Entweder wir fügen eine Suspense-Grenze darüber hinzu oder wir entscheiden uns für Caching.
00:21:09Machen wir zuerst das Einfache und fügen hier einfach eine `loading.tsx` hinzu.
00:21:12Und fügen wir hier eine Ladeseite hinzu,
00:21:17eine schöne Skeleton-UI.
00:21:21Das ist ziemlich gut.
00:21:21Es hat den Fehler behoben,
00:21:22aber es passiert nichts Nützliches auf dieser Seite,
00:21:25während ich warte.
00:21:25Ich kann nicht einmal suchen.
00:21:27Mit Cache-Komponenten ist dynamisch wie – oder statisch versus dynamisch ist wie eine Skala.
00:21:33Und es liegt an uns zu entscheiden,
00:21:35wie viel Statik wir in unseren Seiten haben wollen.
00:21:37Also,
00:21:37verschieben wir diese Seite mehr in Richtung statisch und löschen diese `loading.tsx` wieder.
00:21:43Und dann nutzen wir die Muster,
00:21:44die wir zuvor gelernt haben,
00:21:46um diesen Datenabruf in die Komponente zu verschieben und ihn mit der UI zu ko-lokalisieren.
00:21:50Verschieben Sie dies also hier in meine responsiven Kategoriefilter.
00:21:54Ich habe zwei wegen responsivem Design.
00:21:57Ich kann es tatsächlich einfach hier hinzufügen.
00:22:01Hoppla.
00:22:03Und dies importieren.
00:22:05Ich brauche diese Prop nicht mehr.
00:22:06Tatsächlich wird meine Komponente komponierbarer.
00:22:09Und anstatt es zu suspendieren,
00:22:11fügen wir einfach die `use cache`-Direktive hinzu.
00:22:14Und das sollte genügen.
00:22:16Beachten Sie also,
00:22:17wie ich gezwungen werde,
00:22:18mehr darüber nachzudenken,
00:22:19wo ich meine Promises auflöse und dadurch tatsächlich meine Komponentenarchitektur verbessere.
00:22:24Ich muss dies nicht suspendieren.
00:22:25Dies wird einfach hier in der statischen Shell enthalten sein.
00:22:28Die Produktliste,
00:22:30lassen Sie mich diese einfach frisch halten.
00:22:35Damit ich das jedes Mal neu laden kann.
00:22:37Während die Kategorien unten,
00:22:39diese möchte ich auch zwischenspeichern.
00:22:41Also, gehen wir zum Footer.
00:22:44Und da ich hier das Donut-Muster verwende,
00:22:47kann dies tatsächlich zwischengespeichert werden,
00:22:50obwohl es sich in diesem interaktiven Teil der UI befindet.
00:22:54Das ist also völlig in Ordnung.
00:22:55Dieses Muster war also nicht nur gut für die Komposition,
00:22:57sondern auch für das Caching.
00:22:58Ich glaube, ich habe dort noch einen Fehler.
00:23:03Mal sehen, was das ist.
00:23:04Habe immer noch diesen Fehler.
00:23:08Das liegt tatsächlich an diesen Suchparametern.
00:23:10Suchparameter, wie wir wissen, sind eine dynamische API.
00:23:12Ich kann das nicht zwischenspeichern.
00:23:13Aber ich kann es tiefer auflösen,
00:23:15um mehr von meiner UI freizulegen und sie statisch zu machen.
00:23:18Also,
00:23:18lassen Sie uns dies nach unten verschieben,
00:23:21es als Promise an die Produktliste übergeben.
00:23:24Wir werden dies hier als Promise typisieren, so.
00:23:30Lassen Sie uns es in der Produktliste auflösen,
00:23:33die aufgelösten Suchparameter hier und hier verwenden.
00:23:36Und da dies hier suspendiert ist,
00:23:38wird der Fehler verschwunden sein.
00:23:40Wenn ich dies also neu lade,
00:23:42ist das Einzige,
00:23:43was hier neu geladen wird,
00:23:44nur der Teil,
00:23:45den ich speziell als dynamisch ausgewählt habe.
00:23:48Alles andere kann zwischengespeichert werden.
00:23:49Und das bedeutet,
00:23:50dass ich mit meinem Banner interagieren oder sogar suchen kann,
00:23:54weil dieser Teil bereits vorgerendert wurde.
00:23:57Alles klar,
00:23:58machen wir die letzte Seite hier,
00:24:01die Produktseite,
00:24:02die schwierigste und wichtigste.
00:24:05Es ist im Moment wirklich schlecht.
00:24:08Das ist anscheinend super wichtig für eine E-Commerce-Plattform.
00:24:11Alles klar, beheben wir das auch.
00:24:15Hier habe ich also diese Produktseite.
00:24:18Beginnen wir damit,
00:24:19nur die wiederverwendbaren Inhalte hier zwischenzuspeichern,
00:24:22zum Beispiel das Produkt selbst.
00:24:23Und fügen Sie hier einfach `use cache` hinzu und markieren Sie dies als gecacht.
00:24:27Das sollte in Ordnung sein.
00:24:28Das bedeutet, wir können die Suspense-Grenze hier entfernen.
00:24:33Alles klar,
00:24:33und dies wird hier nicht mehr bei jeder Anfrage neu geladen,
00:24:37richtig?
00:24:38Für die Produktdetails machen wir dasselbe.
00:24:40Fügen wir `use cache` hinzu.
00:24:41Markieren wir es als gecacht und sehen,
00:24:44ob das auch funktioniert.
00:24:47Das hat nicht funktioniert.
00:24:48Tatsächlich ist dies ein anderer Fehler.
00:24:50Es sagt mir,
00:24:50dass ich versuche,
00:24:51dynamische APIs innerhalb dieses gecachten Segments zu verwenden.
00:24:54Und das stimmt.
00:24:54Ich verwende den 'Produkt speichern'-Button, richtig?
00:24:56Das ermöglichte es mir,
00:24:57den gespeicherten Zustand anzuklicken und umzuschalten.
00:25:00Was denken Sie, können wir damit tun?
00:25:03Wir können das Donut-Muster wieder verwenden.
00:25:06Tatsächlich können wir auch dynamische Segmente in Cache-Segmente einfügen.
00:25:10Wir verschachteln sie also wie zuvor, aber mit Cache.
00:25:12Das ist also ziemlich cool.
00:25:14Lassen Sie uns hier die Children so hinzufügen.
00:25:19Und dies wird den Fehler beheben.
00:25:21Und ich kann dies einfach um dieses eine dynamische Segment meiner Seite hier wickeln,
00:25:26die Suspense-Grenze entfernen und nur eine sehr kleine Lesezeichen-UI für dieses eine dynamische Stück der Seite hinzufügen.
00:25:34Und schauen wir mal, wie das jetzt aussieht.
00:25:40Beachten Sie also,
00:25:40wie fast die gesamte UI verfügbar ist,
00:25:42aber ich habe diesen einen kleinen Teil,
00:25:45der dynamisch ist,
00:25:45und das ist in Ordnung.
00:25:47Alles andere ist noch da.
00:25:48Und lassen wir die Bewertungen dynamisch,
00:25:51weil wir sie frisch halten könnten.
00:25:53Es gibt immer noch einen weiteren Fehler.
00:25:54Lassen Sie uns das schnell angehen.
00:25:56Wieder sind dies die `params`.
00:25:58Ich bekomme Hilfe,
00:25:59dass ich eine Wahl treffen muss,
00:26:00entweder einen Lade-Fallback hinzuzufügen oder dies zwischenzuspeichern.
00:26:04Verwenden wir in diesem Fall einfach `generate static params`.
00:26:07Hängt irgendwie von Ihrem Anwendungsfall und Ihrem Datensatz ab.
00:26:10Aber für diesen Fall werde ich einfach ein paar vorgerenderte,
00:26:12vordefinierte Seiten hinzufügen und den Rest dann zwischenspeichern,
00:26:15sobald sie von Benutzern generiert werden.
00:26:17Und dies wird meinen Fehler hier beheben.
00:26:20Ich denke,
00:26:21ich bin tatsächlich mit meinem Refactoring fertig.
00:26:22Lassen Sie uns die bereitgestellte Version ansehen und sehen,
00:26:25wie das aussieht.
00:26:26Ich habe dies also gerade auf Vercel bereitgestellt.
00:26:27Und denken Sie daran,
00:26:30ich habe hier absichtlich viele Datenabrufe verlangsamt.
00:26:35Und trotzdem,
00:26:36wenn ich diese Seite anfänglich lade,
00:26:38ist alles bereits verfügbar.
00:26:40Das Einzige hier sind nur diese wenigen dynamischen Segmente wie die Rabatte und die 'für dich'-Inhalte.
00:26:46Dasselbe gilt für 'Alle durchsuchen'.
00:26:47Die gesamte UI ist bereits verfügbar.
00:26:50Und für das Produkt selbst fühlt es sich einfach sofort an.
00:26:54Und denken Sie noch einmal daran,
00:26:56dass all diese Cache-Segmente mit der statischen Shell durch partielles Pre-Rendering enthalten sein werden.
00:27:00Und es kann mit dem verbesserten Prefetching im neuen Next 16 Client Router vorab abgerufen werden.
00:27:05Das bedeutet also,
00:27:06dass jede Navigation einfach – es fühlt sich einfach so schnell an,
00:27:09oder?
00:27:09Alles klar,
00:27:10zusammenfassend lässt sich sagen: Mit Cache-Komponenten gibt es kein statisch versus dynamisch mehr.
00:27:17Und wir müssen dynamische APIs nicht vermeiden oder dynamische Inhalte kompromittieren.
00:27:28Und wir können diese komplexen Hacks und Workarounds mit mehreren Datenabrufstrategien überspringen,
00:27:33nur für diesen einen – diesen Cache-Hit,
00:27:36wie ich Ihnen gezeigt habe.
00:27:37Im modernen Next.js ist dynamisch versus statisch eine Skala.
00:27:40Und wir entscheiden,
00:27:41wie viel Statik wir in unseren Apps haben wollen.
00:27:43Und solange wir bestimmte Muster befolgen,
00:27:45können wir ein mentales Modell haben,
00:27:47das standardmäßig performant,
00:27:49komponierbar und skalierbar ist.
00:27:50Also, kehren wir zu den Folien zurück.
00:27:53Wenn Sie also nicht – wir nicht schon von der Geschwindigkeit beeindruckt sind,
00:27:55hier ist der Lighthouse-Score.
00:27:56Ich habe also einige Felddaten mit den Vercel Speed Insights gesammelt.
00:28:00Wir haben also einen Score von 100 auf allen wichtigsten Seiten,
00:28:03der Startseite,
00:28:04der Produktseite und der Produktliste,
00:28:06obwohl sie hochdynamisch sind.
00:28:08Fassen wir also abschließend die Muster zusammen,
00:28:10die Skalierbarkeit und Leistung in Next.js-Apps gewährleisten und es uns ermöglichen,
00:28:15die neuesten Innovationen zu nutzen und solche Scores zu erzielen.
00:28:18Erstens können wir unsere Architektur verfeinern,
00:28:21indem wir Promises tief im Komponentenbaum auflösen und Daten lokal innerhalb von Komponenten mit React Cache abrufen,
00:28:26um doppelte Arbeit zu vermeiden.
00:28:28Wir können übermäßiges Prop-Passing an Client-Komponenten vermeiden,
00:28:31indem wir Kontext-Provider in Kombination mit React Use verwenden.
00:28:35Zweitens können wir Server- und Client-Komponenten mithilfe des Donut-Musters zusammensetzen,
00:28:38um clientseitiges JavaScript zu reduzieren,
00:28:40eine klare Trennung der Belange zu gewährleisten und die Wiederverwendung von Komponenten zu ermöglichen.
00:28:43Und dieses Muster wird es uns später ermöglichen,
00:28:46unsere zusammengesetzten Serverkomponenten zwischenzuspeichern.
00:28:50Und schließlich können wir mit `use cache` entweder nach Seite,
00:28:52Komponente oder Funktion cachen und vorrendern,
00:28:55um redundante Verarbeitung zu eliminieren,
00:28:56Leistung und SEO zu steigern und partielles Pre-Rendering diese Segmente der App statisch rendern zu lassen.
00:29:01Und wenn unsere Inhalte wirklich dynamisch sind,
00:29:04können wir sie mit geeigneten Lade-Fallbacks suspendieren.
00:29:07Und denken Sie daran,
00:29:07dass all dies miteinander verbunden ist.
00:29:09Je besser Ihre Architektur ist,
00:29:10desto einfacher ist es,
00:29:10sie zu komponieren,
00:29:11und desto einfacher wird es sein,
00:29:12sie mit den besten Ergebnissen zwischenzuspeichern und vorzurendern.
00:29:15Zum Beispiel ermöglicht das Auflösen dynamischer APIs tief im Baum die Erstellung einer größeren,
00:29:19teilweise vorgerenderten statischen Shell.
00:29:22Und damit ist dies das Repo der fertigen Version der Anwendung.
00:29:25Es gibt so viele Dinge,
00:29:26die ich dort nicht einmal gezeigt habe,
00:29:28die Sie sich ansehen können.
00:29:29Und Sie können den QR-Code scannen,
00:29:31um meine sozialen Medien dort neben dem Repo zu finden,
00:29:33wenn Sie kein Bild machen und es selbst eingeben möchten.
00:29:36Also ja, das war's von mir.
00:29:37Vielen Dank an die Next.js Conf, dass ich hier sein durfte.
00:29:39[MUSIK SPIELT]

Key Takeaway

Modernes Next.js 16 ermöglicht durch die 'use cache'-Direktive und bewährte Architekturmuster wie das Donut-Muster eine granulare Kontrolle über Caching und Rendering, um hochperformante, skalierbare und wartbare Anwendungen zu entwickeln, die sowohl statische als auch dynamische Inhalte effizient verwalten.

Highlights

Next.js 16 führt die 'use cache'-Direktive ein, die komponierbares Caching auf Seiten-, Komponenten- oder Funktionsebene ermöglicht und die Trennung zwischen statischem und dynamischem Rendering aufhebt.

Das Donut-Muster ist eine effektive Architekturstrategie, um clientseitiges JavaScript zu reduzieren, die Trennung der Belange zu verbessern und die Wiederverwendbarkeit von Komponenten zu fördern.

Durch das Auflösen von Promises tief im Komponentenbaum und die Nutzung von React Cache können Prop-Drilling vermieden und Komponenten modularer gestaltet werden.

Partielles Pre-Rendering in Kombination mit 'use cache' ermöglicht es, statische Teile einer Seite vorab zu rendern und in die statische Shell aufzunehmen, was die initiale Ladezeit erheblich verbessert.

Die neuen Caching-Strategien helfen, blockierende Routen zu identifizieren und die Gesamtleistung sowie die Benutzererfahrung von Next.js-Anwendungen zu optimieren.

Die Anwendung dieser Muster führt zu beeindruckenden Lighthouse-Scores von 100, selbst bei hochdynamischen E-Commerce-Anwendungen.

Timeline

Einführung und Grundlagen des Renderings

Aurora stellt sich als Webentwicklerin vor und leitet das Thema Komposition, Caching und Architektur in modernem Next.js ein. Sie beginnt mit einer Auffrischung der Konzepte von statischem und dynamischem Rendering im Next.js App Router. Statisches Rendering wird als Methode zur Erstellung schnellerer, global verteilter Websites mit reduzierter Serverlast und verbesserter SEO beschrieben. Dynamisches Rendering hingegen ermöglicht die Anzeige von Echtzeit- oder personalisierten Daten und den Zugriff auf anfragezeitspezifische Informationen wie Cookies und Header, die eine Seite dynamisch machen können.

Herausforderungen und die 'use cache'-Direktive

In früheren Next.js-Versionen führte eine einzige dynamische API auf einer Seite dazu, dass die gesamte Seite dynamisch gerendert wurde, was zu redundanter Serververarbeitung führte. React Server Components mit Suspense ermöglichten zwar das Streaming dynamischer Inhalte, aber nicht-dynamische asynchrone Komponenten wurden dennoch zur Anfragezeit ausgeführt. Zur Lösung dieses Problems wurde die 'use cache'-Direktive in Next.js 16 eingeführt. Diese Direktive ermöglicht komponierbares Caching auf Seiten-, Komponenten- oder Funktionsebene, wodurch Next.js nicht mehr raten muss, was eine Seite ist, und statische sowie dynamische Inhalte gleichzeitig verarbeitet werden können.

Demo-Anwendung und identifizierte Probleme

Die Sprecherin präsentiert eine einfache E-Commerce-Anwendung, die als Grundlage für die Demo dient. Sie zeigt verschiedene Seiten wie die Startseite, eine 'Alle durchsuchen'-Seite, eine 'Über uns'-Seite und ein personalisiertes Dashboard. Die Anwendung weist eine Mischung aus statischen und dynamischen Inhalten auf, was die Notwendigkeit effizienter Rendering-Strategien unterstreicht. Die identifizierten Probleme in der Codebasis sind tiefes Prop-Drilling, übermäßiges clientseitiges JavaScript, große Komponenten mit mehreren Verantwortlichkeiten und das Fehlen von statischem Rendering, was zu hohen Serverkosten und schlechter Leistung führt.

Prop-Drilling beheben und Datenabruf ko-lokalisieren

Das erste Problem, das angegangen wird, ist das Prop-Drilling der 'loggedIn'-Variable. Die beste Praxis bei Serverkomponenten ist es, den Datenabruf in die Komponenten zu verschieben, die die Daten tatsächlich verwenden, und Promises tiefer im Baum aufzulösen. Die Sprecherin demonstriert, wie ein 'AuthProvider' im Root-Layout verwendet werden kann, um den 'loggedIn'-Status als Promise weiterzugeben, der dann lokal in Client-Komponenten mit 'useAuth' und 'use' gelesen wird. Dies macht Komponenten wiederverwendbarer und komponierbarer, da sie keine unnötigen Abhängigkeiten mehr von übergeordneten Komponenten haben.

Clientseitiges JavaScript reduzieren mit dem Donut-Muster

Das 'WelcomeBanner' ist eine Client-Komponente aufgrund einer einfachen 'entlassen'-Funktion und verwendet SWR für clientseitiges Abrufen, was zu unnötigem JavaScript und einer Verletzung der Trennung der Belange führt. Die Lösung ist das 'Donut-Muster', bei dem die interaktive Logik in einen clientseitigen Wrapper ('BannerContainer') extrahiert wird, der serverseitig gerenderte Inhalte als 'children' aufnimmt. Dies ermöglicht es, die Hauptkomponente in eine Serverkomponente umzuwandeln, serverseitiges Abrufen zu nutzen und clientseitiges JavaScript zu minimieren. Das Muster wird auch für andere Komponenten wie 'ShowMore' und Animations-Wrapper angewendet, um die Komposition und Wiederverwendbarkeit zu verbessern.

Statische Rendering-Strategien mit 'use cache' anwenden

Das Hauptproblem ist, dass alle Seiten dynamisch gerendert werden, da das Root-Layout Cookies für das Benutzerprofil verwendet. Die Aktivierung von 'cache components' in der Next.js-Konfiguration macht alle asynchronen Aufrufe dynamisch und ermöglicht die granulare 'use cache'-Direktive. Die Sprecherin wendet 'use cache' auf statische Segmente der Startseite an, wie Hero-Bereich und Feature-Kategorien, um partielles Pre-Rendering zu nutzen und Suspense-Grenzen zu entfernen. Auf der 'Alle durchsuchen'-Seite werden blockierende Routen identifiziert und der Datenabruf für Kategorien ko-lokalisiert und gecacht. Dynamische APIs wie 'search params' werden tiefer im Baum aufgelöst und mit Suspense umwickelt, während der Rest der Seite gecacht wird. Schließlich wird auf der Produktseite das Produkt und die Produktdetails gecacht, wobei das Donut-Muster für dynamische Elemente wie den 'Produkt speichern'-Button verwendet wird und 'generate static params' für die Vorab-Generierung von Produktseiten zum Einsatz kommt.

Bereitstellung, Leistung und Fazit

Die optimierte Anwendung wird auf Vercel bereitgestellt, und die Sprecherin demonstriert die sofortige Verfügbarkeit statischer Inhalte und die reibungslose Interaktion, trotz absichtlich verlangsamter Datenabrufe. Sie hebt hervor, dass partielles Pre-Rendering und verbessertes Prefetching in Next.js 16 zu einer extrem schnellen Benutzererfahrung führen. Abschließend fasst sie zusammen, dass 'use cache' das Dilemma zwischen statisch und dynamisch auflöst und granulare Kontrolle ermöglicht. Die Anwendung der besprochenen Muster führt zu beeindruckenden Lighthouse-Scores von 100 auf wichtigen Seiten, selbst bei hochdynamischen Inhalten. Eine bessere Architektur, die Promises tief auflöst und das Donut-Muster nutzt, ist der Schlüssel zu optimaler Komposition, Caching und Leistung.

Community Posts

View all posts