Eine vollständige Anleitung zur inkrementellen statischen Regenerierung (ISR) mit Next.js
Veröffentlicht: 2022-03-10Vor einem Jahr hat Next.js 9.3 die Unterstützung für Static Site Generation (SSG) veröffentlicht und ist damit das erste Hybrid-Framework. Zu diesem Zeitpunkt war ich seit einigen Jahren ein zufriedener Next.js-Benutzer, aber diese Version machte Next.js zu meiner neuen Standardlösung. Nachdem ich intensiv mit Next.js gearbeitet hatte, kam ich zu Vercel, um Unternehmen wie Tripadvisor und Washington Post bei der Einführung und Skalierung von Next.js zu unterstützen.
In diesem Artikel möchte ich eine neue Evolution des Jamstacks untersuchen: Incremental Static Regeneration (ISR) . Nachfolgend finden Sie einen Leitfaden zu ISR – einschließlich Anwendungsfällen, Demos und Kompromissen.
Das Problem mit der Static-Site-Generierung
Die Idee hinter dem Jamstack ist ansprechend: vorgerenderte statische Seiten, die auf ein CDN gepusht werden können und in Sekundenschnelle global verfügbar sind. Statische Inhalte sind schnell, ausfallsicher und werden sofort von Crawlern indiziert. Aber es gibt einige Probleme.
Wenn Sie die Jamstack-Architektur übernommen haben, während Sie eine umfangreiche statische Website erstellt haben, müssen Sie möglicherweise stundenlang warten, bis Ihre Website erstellt wurde. Wenn Sie die Anzahl der Seiten verdoppeln, verdoppelt sich auch die Bauzeit. Betrachten wir Target.com. Ist es möglich, bei jeder Bereitstellung Millionen von Produkten statisch zu generieren?
Selbst wenn jede Seite statisch in unrealistischen 1 ms generiert wurde, würde es immer noch Stunden dauern, die gesamte Website neu aufzubauen . Für große Webanwendungen ist die Wahl einer vollständigen Generierung statischer Sites ein Fehlstart. Große Teams benötigen eine flexiblere, personalisierte Hybridlösung.
Content-Management-Systeme (CMS)
Für viele Teams ist der Inhalt ihrer Website vom Code entkoppelt. Die Verwendung eines Headless CMS ermöglicht es Content-Redakteuren, Änderungen zu veröffentlichen, ohne einen Entwickler einzubeziehen. Bei herkömmlichen statischen Websites kann dieser Vorgang jedoch langsam sein.
Stellen Sie sich einen E-Commerce-Shop mit 100.000 Produkten vor. Produktpreise ändern sich häufig. Wenn ein Content-Redakteur im Rahmen einer Werbeaktion den Preis für Kopfhörer von 100 $ auf 75 $ ändert, verwendet sein CMS einen Webhook, um die gesamte Website neu aufzubauen. Es ist nicht möglich, stundenlang auf den neuen Preis zu warten.
Lange Builds mit unnötiger Berechnung können auch zusätzliche Kosten verursachen. Idealerweise ist Ihre Anwendung intelligent genug, um zu verstehen, welche Produkte geändert wurden, und diese Seiten inkrementell zu aktualisieren, ohne dass eine vollständige Neuerstellung erforderlich ist .
Inkrementelle statische Regeneration (ISR)
Mit Next.js können Sie statische Seiten erstellen oder aktualisieren, nachdem Sie Ihre Website erstellt haben. Incremental Static Regeneration (ISR) ermöglicht es Entwicklern und Content-Editoren, die statische Generierung auf Seitenbasis zu verwenden, ohne die gesamte Website neu erstellen zu müssen . Mit ISR können Sie die Vorteile der Statik beibehalten und gleichzeitig auf Millionen von Seiten skalieren.
Statische Seiten können zur Laufzeit (on-demand) anstatt zur Build-Zeit mit ISR generiert werden. Mithilfe von Analysen, A/B-Tests oder anderen Metriken sind Sie mit der Flexibilität ausgestattet, Ihre eigenen Kompromisse bei den Build-Zeiten einzugehen.
Betrachten Sie den E-Commerce-Shop von früher mit 100.000 Produkten. Bei realistischen 50 ms zum statischen Generieren jeder Produktseite würde dies ohne ISR fast 2 Stunden dauern . Bei ISR haben wir die Wahl zwischen:
- Schnellere Builds
Generieren Sie die beliebtesten 1.000 Produkte zur Bauzeit. Anfragen an andere Produkte sind ein Cache-Mißerfolg und generieren statisch On-Demand: 1-Minute-Builds. - Höhere Cache-Trefferrate
Generieren Sie 10.000 Produkte zur Build-Zeit, um sicherzustellen, dass mehr Produkte vor einer Benutzeranfrage zwischengespeichert werden: 8-Minuten-Builds.
Lassen Sie uns ein Beispiel für ISR für eine E-Commerce-Produktseite durchgehen.
Einstieg
Abrufen von Daten
Wenn Sie Next.js noch nie verwendet haben, empfehle ich Ihnen, Erste Schritte mit Next.js zu lesen, um die Grundlagen zu verstehen. ISR verwendet dieselbe Next.js-API, um statische Seiten zu generieren: getStaticProps
. Durch Angabe von revalidate: 60
teilen wir Next.js mit, ISR für diese Seite zu verwenden.
- Next.js kann eine Revalidierungszeit pro Seite definieren. Stellen wir es auf 60 Sekunden ein.
- Die erste Anfrage an die Produktseite zeigt die zwischengespeicherte Seite mit dem ursprünglichen Preis.
- Die Daten zum Produkt werden im CMS aktualisiert.
- Alle Anfragen an die Seite nach der ersten Anfrage und vor 60 Sekunden werden zwischengespeichert und sofort ausgeführt.
- Nach dem 60-Sekunden-Fenster zeigt die nächste Anfrage immer noch die zwischengespeicherte (veraltete) Seite. Next.js löst im Hintergrund eine Neugenerierung der Seite aus.
- Sobald die Seite erfolgreich generiert wurde, macht Next.js den Cache ungültig und zeigt die aktualisierte Produktseite an. Wenn die Regenerierung im Hintergrund fehlschlägt, bleibt die alte Seite unverändert.
// pages/products/[id].js export async function getStaticProps({ params }) { return { props: { product: await getProductFromDatabase(params.id) }, revalidate: 60 } }
Pfade generieren
Next.js definiert, welche Produkte zur Erstellungszeit und welche nach Bedarf generiert werden sollen. Lassen Sie uns nur die 1.000 beliebtesten Produkte zur Erstellungszeit generieren, indem getStaticPaths
eine Liste der 1.000 wichtigsten Produkt-IDs bereitstellen.
Wir müssen konfigurieren, wie Next.js „zurückfällt“, wenn eines der anderen Produkte nach dem ersten Build angefordert wird. Es stehen zwei Optionen zur Auswahl: blocking
und true
.
-
fallback: blocking
(bevorzugt)
Wenn eine Anfrage an eine Seite gestellt wird, die noch nicht generiert wurde, rendert Next.js die Seite bei der ersten Anfrage auf dem Server. Zukünftige Anfragen werden die statische Datei aus dem Cache bereitstellen. -
fallback: true
Wenn eine Anfrage an eine Seite gestellt wird, die noch nicht generiert wurde, stellt Next.js bei der ersten Anfrage sofort eine statische Seite mit einem Ladezustand bereit. Wenn die Daten vollständig geladen sind, wird die Seite mit den neuen Daten erneut gerendert und zwischengespeichert. Zukünftige Anfragen werden die statische Datei aus dem Cache bereitstellen.
// pages/products/[id].js export async function getStaticPaths() { const products = await getTop1000Products() const paths = products.map((product) => ({ params: { id: product.id } })) return { paths, fallback: 'blocking' } }
Kompromisse
Next.js konzentriert sich in erster Linie auf den Endbenutzer. Die „beste Lösung“ ist relativ und variiert je nach Branche, Zielgruppe und Art der Anwendung. Indem es Entwicklern ermöglicht, zwischen Lösungen zu wechseln, ohne die Grenzen des Frameworks zu verlassen, können Sie mit Next.js das richtige Tool für das Projekt auswählen.
Serverseitiges Rendern
ISR ist nicht immer die richtige Lösung. Beispielsweise kann der Facebook-Newsfeed keine veralteten Inhalte anzeigen. In diesem Fall möchten Sie SSR und möglicherweise Ihre eigenen cache-control
Header mit Ersatzschlüsseln verwenden, um Inhalte ungültig zu machen. Da Next.js ein hybrides Framework ist, können Sie diesen Kompromiss selbst eingehen und innerhalb des Frameworks bleiben.
// You can cache SSR pages at the edge using Next.js // inside both getServerSideProps and API Routes res.setHeader('Cache-Control', 's-maxage=60, stale-while-revalidate');
SSR und Edge-Caching ähneln ISR (insbesondere bei Verwendung von stale-while-revalidate
Caching-Headern), wobei der Hauptunterschied in der ersten Anforderung besteht. Mit ISR kann die erste Anfrage statisch garantiert werden, wenn sie vorgerendert wird. Selbst wenn Ihre Datenbank ausfällt oder ein Problem bei der Kommunikation mit einer API auftritt, sehen Ihre Benutzer immer noch die ordnungsgemäß bereitgestellte statische Seite. SSR ermöglicht es Ihnen jedoch, Ihre Seite basierend auf der eingehenden Anfrage anzupassen.
Hinweis : Die Verwendung von SSR ohne Caching kann zu schlechter Leistung führen. Jede Millisekunde zählt, wenn es darum geht, den Benutzer daran zu hindern, Ihre Website zu sehen, und dies kann dramatische Auswirkungen auf Ihre TTFB (Time to First Byte) haben.
Static-Site-Generierung
ISR ist für kleine Websites nicht immer sinnvoll. Wenn Ihr Revalidierungszeitraum länger ist als die Zeit, die für die Neuerstellung Ihrer gesamten Site benötigt wird, können Sie auch die herkömmliche Generierung statischer Sites verwenden.
Clientseitiges Rendern
Wenn Sie React ohne Next.js verwenden, verwenden Sie clientseitiges Rendering. Ihre Anwendung dient einem Ladezustand, gefolgt von der Anforderung von Daten innerhalb von JavaScript auf der Client-Seite (z. B. useEffect
). Während dies Ihre Optionen für das Hosting erhöht (da kein Server erforderlich ist), gibt es Kompromisse.
Das Fehlen von vorgerenderten Inhalten aus dem anfänglichen HTML führt zu einer langsameren und weniger dynamischen Suchmaschinenoptimierung (SEO). Es ist auch nicht möglich, CSR mit deaktiviertem JavaScript zu verwenden.
ISR-Fallback-Optionen
Wenn Ihre Daten schnell abgerufen werden können, sollten Sie fallback: blocking
verwenden. Dann brauchen Sie den Ladezustand nicht zu berücksichtigen und Ihre Seite zeigt immer das gleiche Ergebnis (unabhängig davon, ob sie zwischengespeichert ist oder nicht). Wenn Ihr Datenabruf langsam ist, können Sie mit fallback: true
dem Benutzer sofort einen Ladestatus anzeigen.
ISR: Nicht nur Caching!
Während ich ISR im Zusammenhang mit einem Cache erklärt habe, ist es so konzipiert, dass Ihre generierten Seiten zwischen Bereitstellungen bestehen bleiben . Dies bedeutet, dass Sie sofort ein Rollback durchführen können und Ihre zuvor generierten Seiten nicht verlieren.
Jede Bereitstellung kann durch eine ID verschlüsselt werden, die Next.js verwendet, um statisch generierte Seiten beizubehalten. Wenn Sie ein Rollback durchführen, können Sie den Schlüssel so aktualisieren, dass er auf die vorherige Bereitstellung verweist, was atomare Bereitstellungen ermöglicht. Das bedeutet, dass Sie Ihre vorherigen unveränderlichen Bereitstellungen aufrufen können und sie wie beabsichtigt funktionieren.
- Hier ist ein Beispiel für das Zurücksetzen von Code mit ISR:
- Sie drücken Code und erhalten eine Bereitstellungs-ID 123.
- Ihre Seite enthält einen Tippfehler „Smshng Magazine“.
- Sie aktualisieren die Seite im CMS. Keine erneute Bereitstellung erforderlich.
- Sobald auf Ihrer Seite „Smashing Magazine“ angezeigt wird, wird sie dauerhaft gespeichert.
- Sie pushen einen schlechten Code und stellen ID 345 bereit.
- Sie führen ein Rollback auf Bereitstellungs-ID 123 durch.
- Sie sehen immer noch „Smashing Magazine“.
Zurücksetzungen und dauerhafte statische Seiten liegen außerhalb des Bereichs von Next.js und hängen von Ihrem Hosting-Provider ab. Beachten Sie, dass sich ISR vom Server-Rendering mit Cache-Control
Headern unterscheidet, da Caches ablaufen. Sie werden nicht über Regionen hinweg geteilt und werden beim Zurücksetzen gelöscht.
Beispiele für inkrementelle statische Regenerierung
Die inkrementelle statische Regeneration eignet sich gut für E-Commerce, Marketingseiten, Blogbeiträge, werbefinanzierte Medien und mehr.
- E-Commerce-Demo
Next.js Commerce ist ein All-in-One-Starterkit für leistungsstarke E-Commerce-Websites. - GitHub Reactions-Demo
Reagieren Sie auf das ursprüngliche GitHub-Problem und beobachten Sie, wie ISR die statisch generierte Zielseite aktualisiert. - Statische Tweets-Demo
Dieses Projekt wird in 30 Sekunden bereitgestellt, kann aber mit ISR statisch 500 Millionen Tweets bei Bedarf generieren.
Lernen Sie noch heute Next.js kennen
Entwickler und große Teams entscheiden sich für Next.js wegen seines hybriden Ansatzes und der Fähigkeit, Seiten bei Bedarf inkrementell zu generieren. Mit ISR erhalten Sie die Vorteile der Statik mit der Flexibilität des Server-Renderings. ISR funktioniert out of the box mit next start
.
Next.js wurde für eine schrittweise Einführung entwickelt. Mit Next.js können Sie Ihren bestehenden Code weiterverwenden und so viel (oder so wenig) React hinzufügen, wie Sie benötigen. Indem Sie klein anfangen und schrittweise weitere Seiten hinzufügen, können Sie verhindern, dass die Arbeit der Funktionen entgleist, indem Sie ein vollständiges Neuschreiben vermeiden. Erfahren Sie mehr über Next.js – und allen viel Spaß beim Programmieren!
Weiterführende Lektüre
- Erste Schritte mit Next.js
- Vergleich von Styling-Methoden in Next.js
- So erstellen Sie einen GraphQL-Server mit Next.js-API-Routen