Verwendung von SWR React Hooks mit der inkrementellen statischen Regeneration (ISR) von Next.js
Veröffentlicht: 2022-03-10Wenn Sie jemals Incremental Static Regeneration (ISR) mit Next.js verwendet haben, haben Sie möglicherweise festgestellt, dass Sie veraltete Daten an den Client senden. Dies tritt auf, wenn Sie die Seite auf dem Server erneut validieren. Bei manchen Websites funktioniert das, aber bei anderen (z. B. Hack Club's Scrapbook, einer Website, die von @lachlanjc erstellt wurde und bei deren Pflege ich helfe) erwartet der Benutzer, dass die Daten auf dem neuesten Stand gehalten werden.
Die erste Lösung, die Ihnen in den Sinn kommt, besteht darin, die Seiten einfach serverseitig zu rendern und sicherzustellen, dass der Client immer die aktuellsten Daten erhält. Das Abrufen großer Datenblöcke vor dem Rendern kann jedoch das anfängliche Laden der Seite verlangsamen. Die in Scrapbook verwendete Lösung bestand darin, die SWR-Bibliothek von React-Hooks zu verwenden, um die zwischengespeicherte Seite vom Server mit clientseitigem Datenabruf zu aktualisieren . Dieser Ansatz stellt sicher, dass die Benutzer immer noch eine gute Erfahrung machen, dass die Seite schnell ist und dass die Daten auf dem neuesten Stand gehalten werden.
Lernen Sie den SWR kennen
SWR ist eine von Vercel erstellte React Hooks-Bibliothek, der Name kommt von dem Begriff stale-while-revalidate. Wie der Name schon sagt, werden Ihrem Client veraltete/alte Daten bereitgestellt, während die aktuellsten Daten durch SWR auf der Clientseite abgerufen (erneut validiert) werden. SWR validiert die Daten nicht nur einmal, Sie können SWR jedoch so konfigurieren, dass die Daten in einem Intervall erneut validiert werden, wenn die Registerkarte den Fokus wiedererlangt, wenn ein Client sich wieder mit dem Internet verbindet oder programmgesteuert.
In Verbindung mit den API-Routen von ISR und Next.js kann SWR verwendet werden, um eine reaktionsschnelle Benutzererfahrung zu schaffen. Dem Client wird zuerst die zwischengespeicherte statisch generierte Seite (generiert mit getStaticProps()
) bereitgestellt, im Hintergrund beginnt der Server auch mit dem Prozess der erneuten Validierung dieser Seite (lesen Sie hier mehr). Dieser Prozess fühlt sich für den Kunden schnell an und er kann jetzt den Datensatz sehen, er kann jedoch etwas veraltet sein. Sobald die Seite geladen ist, wird eine Abrufanforderung an eine Next.js-API-Route von Ihnen gesendet, die dieselben Daten zurückgibt, die mit getStaticProps()
generiert wurden. Wenn diese Anfrage abgeschlossen ist (vorausgesetzt, sie war erfolgreich), aktualisiert der SWR die Seite mit diesen neuen Daten.
Lassen Sie uns nun auf Scrapbook zurückblicken und wie dies dazu beigetragen hat, das Problem veralteter Daten auf der Seite zu lösen . Das Offensichtliche ist, dass der Client jetzt eine aktualisierte Version erhält. Interessanter ist jedoch der Einfluss auf die Geschwindigkeit unserer Seite. Wenn wir die Geschwindigkeit durch Lighthouse messen, erhalten wir einen Geschwindigkeitsindex von 1,5 Sekunden für die ISR + SWR-Variante der Website und 5,8 Sekunden für die Server Side Rendering-Variante (plus eine Warnung bezüglich der anfänglichen Serverantwortzeit). Das ist ein ziemlich starker Kontrast zwischen den beiden (und es war auch beim Laden der Seiten bemerkbar). Aber es gibt auch einen Kompromiss, auf der serverseitig gerenderten Seite hat der Benutzer das Layout der Website nach ein paar Sekunden nicht geändert, wenn neue Daten eingehen. Obwohl ich glaube, dass Scrapbook dieses Update gut handhabt, ist es eine wichtige Überlegung, wann Gestaltung Ihrer Benutzererfahrung.
Wo man SWR verwendet (und wo nicht)
SWR kann an einer Vielzahl von Orten eingesetzt werden, hier sind ein paar Website-Kategorien, in die SWR hervorragend passen würde:
- Websites mit Live-Daten, die schnell aktualisiert werden müssen.
Beispiele für solche Seiten wären Sportergebnisse und Flugverfolgung. Beim Erstellen dieser Sites sollten Sie die Option Revalidate on interval mit einer niedrigen Intervalleinstellung (eins bis fünf Sekunden) verwenden. - Websites mit einem Feed-Stil von Updates oder Posts, die in Echtzeit aktualisiert werden.
Das klassische Beispiel hierfür sind die Nachrichtenseiten, die Live-Blogs von Ereignissen wie Wahlen haben. Ein weiteres Beispiel wäre das oben erwähnte Scrapbook. In diesem Fall möchten Sie wahrscheinlich auch die Option „Im Intervall erneut validieren“ verwenden, jedoch mit einer höheren Intervalleinstellung (dreißig bis sechzig Sekunden), um die Datennutzung zu sparen und unnötige API-Aufrufe zu vermeiden. - Websites mit eher passiven Datenaktualisierungen, die häufig im Hintergrund geöffnet bleiben.
Beispiele für diese Seiten wären Wetterseiten oder in den 2020er Jahren COVID-19-Fallzahlenseiten. Diese Seiten werden nicht so häufig aktualisiert und benötigen daher nicht die ständige Neuvalidierung der beiden vorherigen Beispiele. Es würde jedoch immer noch die Benutzererfahrung verbessern, wenn die Daten aktualisiert werden. In diesen Fällen würde ich empfehlen, das Datum erneut zu validieren, an dem die Registerkarte den Fokus wiedererlangt und wenn ein Client sich wieder mit dem Internet verbindet erhalten Sie diese Daten schnell. - Websites mit kleinen Datenmengen, mit denen Benutzer interagieren können.
Denken Sie an den Youtube-Abonnieren-Button. Wenn Sie auf „Abonnieren“ klicken, möchten Sie sehen, wie sich die Anzahl ändert, und das Gefühl haben, etwas bewirkt zu haben. In diesen Fällen können Sie die Daten programmgesteuert mit SWR erneut validieren, um die neue Zählung abzurufen und den angezeigten Betrag zu aktualisieren.
Zu beachten ist, dass diese alle mit oder ohne ISR angewendet werden können.
Es gibt natürlich einige Orte, an denen Sie SWR nicht oder ohne ISR verwenden möchten. SWR nützt nicht viel, wenn sich Ihre Daten nicht oder nur sehr selten ändern, und kann stattdessen Ihre Netzwerkanfragen verstopfen und die Daten mobiler Benutzer verbrauchen. SWR kann mit Seiten arbeiten, die eine Authentifizierung erfordern, jedoch sollten Sie in diesen Fällen serverseitiges Rendering und nicht die inkrementelle statische Regenerierung verwenden.
Verwenden von SWR mit Next.js und inkrementeller statischer Regeneration
Nachdem wir nun die Theorie dieser Strategie untersucht haben, wollen wir untersuchen, wie wir sie in die Praxis umsetzen. Dafür werden wir eine Website erstellen, die zeigt, wie viele Taxis in Singapur (wo ich lebe!) verfügbar sind, indem wir diese von der Regierung bereitgestellte API verwenden.
Projektstruktur
Unser Projekt funktioniert mit drei Dateien:
-
lib/helpers.js
-
pages/index.js
(unsere Frontend-Datei) -
pages/api/index.js
(unsere API-Datei)
Unsere Hilfsdatei exportiert eine Funktion ( getTaxiData
), die die Daten von der externen API abruft und sie dann in einem geeigneten Format für unsere Verwendung zurückgibt. Unsere API-Datei importiert diese Funktion und setzt ihren Standardexport auf eine Handler-Funktion, die die getTaxiData
Funktion aufruft und sie dann zurückgibt. Dies bedeutet, dass das Senden einer GET-Anforderung an /api
unsere Daten zurückgibt.
Wir benötigen diese Fähigkeit, damit SWR clientseitige Daten abrufen kann. Zuletzt importieren wir in unsere Frontend-Datei getTaxiData
und verwenden es in getStaticProps
. Die Daten werden an die Standard-Exportfunktion unserer Frontend-Datei übergeben, die unsere React-Seite rendert. Wir tun dies alles, um Codeduplizierung zu verhindern und die Konsistenz unserer Daten sicherzustellen. Was für ein Bissen, fangen wir jetzt mit der Programmierung an.
Die Helferdatei
Wir beginnen mit der Erstellung der Funktion getTaxiData
in lib/helpers.js
:
export async function getTaxiData(){ let data = await fetch("https://api.data.gov.sg/v1/transport/taxi-availability").then(r => r.json()) return {taxis: data.features.properties[0].taxi_count, updatedAt: data.features.properties[0].timestamp} }
Die API-Datei
Anschließend erstellen wir die Handler-Funktion in api/index.js
und importieren die getTaxiData
Funktion:
import { getTaxiData } from '../../lib/helpers' export default async function handler(req, res){ res.status(200).json(await getTaxiData()) }
Abgesehen von der oben erwähnten Projektstruktur gibt es hier nichts Einzigartiges für SWR oder ISR. Das Zeug beginnt jetzt in index.js
!
Die Front-End-Datei
Als erstes wollen wir unsere getStaticProps
Funktion erstellen! Diese Funktion importiert unsere getTaxiData
Funktion, verwendet sie und gibt dann die Daten mit einigen zusätzlichen Konfigurationen zurück.
export async function getStaticProps(){ const { getTaxiData } = require("../lib/helpers") return { props: (await getTaxiData()), revalidate: 1 } }
Ich möchte mich auf den Revalidierungsschlüssel in unserem zurückgegebenen Objekt konzentrieren. Diese Taste aktiviert praktisch die inkrementelle statische Regeneration. Es teilt Ihrem Host mit, dass jede Sekunde das Neugenerieren der statischen Seite eine verfügbare Option ist, diese Option wird dann im Hintergrund ausgelöst, wenn ein Client Ihre Seite besucht. Hier können Sie mehr über die inkrementelle statische Regeneration (ISR) lesen.
Es ist jetzt an der Zeit, SWR zu verwenden! Importieren wir es zuerst:
import useSWR from 'swr'
Wir werden SWR in unserer React-Rendering-Funktion verwenden, also erstellen wir diese Funktion:
export default function App(props){ }
Wir erhalten die Requisiten von getStaticProps
. Jetzt können wir SWR einrichten:
const fetcher = (...args) => fetch(...args).then(res => res.json()) const { data } = useSWR("/api", fetcher, {fallbackData: props, refreshInterval: 30000})
Lassen Sie uns das aufschlüsseln. Zuerst definieren wir den Abrufer. Dies wird vom SWR als Argument benötigt, damit es weiß, wie es Ihre Daten abrufen kann, da verschiedene Frameworks usw. unterschiedliche Einstellungen haben können. In diesem Fall verwende ich die auf der SWR-Dokumentationsseite bereitgestellte Funktion. Dann rufen wir den useSWR
Hook mit drei Argumenten auf: dem Pfad zum Abrufen von Daten, der Abruffunktion und dann einem Optionsobjekt.
In diesem options
haben wir zwei Dinge angegeben:
- Die Fallback-Daten;
- Das Intervall, in dem SWR die Daten erneut validieren soll.
In der Fallback-Datenoption stellen wir die von getStaticProps
abgerufenen Daten bereit, wodurch sichergestellt wird, dass die Daten von Anfang an sichtbar sind. Zuletzt verwenden wir die Objektdestrukturierung, um die Daten aus dem Hook zu extrahieren.
Zum Abschluss rendern wir diese Daten mit einem sehr einfachen JSX:
return <div>As of {data.updatedAt}, there are {data.taxis} taxis available in Singapore!</div>
Und wir haben es geschafft! Dort haben wir ein sehr einfaches Beispiel für die Verwendung von SWR mit inkrementeller statischer Regeneration. (Die Quelle unseres Beispiels ist hier verfügbar.)
Wenn Sie bei ISR jemals auf veraltete Daten stoßen, wissen Sie, an wen Sie sich wenden müssen: SWR.
Weiterführende Literatur zu SmashingMag
- SWR React Hooks-Bibliothek
- Eine Einführung in SWR: Reaktionshaken für das Abrufen von Ferndaten, Ibrahima Ndaw
- ISR vs. DPR: Große Worte, schnelle Erklärung, Cassidy Williams
- Globales vs. lokales Styling in Next.js, Alexander Dubovoj
- Clientseitiges Routing in Next.js, Adebiyi Adedotun Lukman