Kompletny przewodnik po przyrostowej regeneracji statycznej (ISR) z Next.js

Opublikowany: 2022-03-10
Krótkie podsumowanie ↬ Incremental Static Regeneration (ISR) to nowa ewolucja platformy Jamstack, która umożliwia natychmiastową aktualizację statycznej zawartości bez konieczności pełnego przebudowy witryny. Hybrydowe podejście Next.js umożliwia korzystanie z ISR w handlu elektronicznym, stronach marketingowych, postach na blogach, mediach z reklamami i nie tylko.

Rok temu Next.js 9.3 udostępnił wsparcie dla Static Site Generation (SSG), czyniąc go pierwszym frameworkiem hybrydowym. Byłem szczęśliwym użytkownikiem Next.js już od kilku lat, ale to wydanie uczyniło Next.js moim nowym domyślnym rozwiązaniem. Po intensywnej współpracy z Next.js dołączyłem do Vercel, aby pomóc firmom takim jak Tripadvisor i Washington Post w adaptacji i skalowaniu Next.js.

W tym artykule chciałbym zbadać nową ewolucję Jamstack: Incremental Static Regeneration (ISR) . Poniżej znajdziesz przewodnik po ISR — zawierający przypadki użycia, dema i kompromisy.

Problem z generowaniem statycznych witryn

Idea stojąca za Jamstack jest atrakcyjna: wstępnie wyrenderowane statyczne strony, które można przesłać do CDN i uzyskać globalnie w ciągu kilku sekund. Treść statyczna jest szybka, odporna na przestoje i natychmiast indeksowana przez roboty indeksujące. Ale są pewne problemy.

Jeśli zaadaptowałeś architekturę Jamstack podczas tworzenia statycznej witryny na dużą skalę, możesz utknąć godzinami w oczekiwaniu na utworzenie witryny. Jeśli podwoisz liczbę stron, czas kompilacji również się podwaja. Rozważmy Target.com. Czy przy każdym wdrożeniu można statycznie generować miliony produktów?

Wykres czasu budowy
Problem z generowaniem statycznej witryny: Ponieważ czas kompilacji skaluje się liniowo wraz z liczbą stron, możesz utknąć w oczekiwaniu godzinami na zbudowanie witryny. (duży podgląd)

Nawet jeśli każda strona byłaby statycznie generowana w nierealistycznym czasie 1 ms, odbudowanie całej witryny zajęłoby wiele godzin . W przypadku dużych aplikacji internetowych wybór pełnego generowania witryn statycznych nie jest konieczny. Zespoły na dużą skalę potrzebują bardziej elastycznego, spersonalizowanego, hybrydowego rozwiązania.

Systemy zarządzania treścią (CMS)

W wielu zespołach zawartość ich witryny jest oddzielona od kodu. Korzystanie z Headless CMS umożliwia edytorom treści publikowanie zmian bez angażowania programisty. Jednak w przypadku tradycyjnych witryn statycznych proces ten może być powolny.

Rozważ sklep e-commerce ze 100 000 produktów. Ceny produktów często się zmieniają. Kiedy redaktor treści zmienia cenę słuchawek ze 100 na 75 USD w ramach promocji, jego system CMS używa webhooka do odbudowy całej witryny. Nie można czekać godzinami na uwzględnienie nowej ceny.

Długie kompilacje z niepotrzebnymi obliczeniami mogą również wiązać się z dodatkowymi kosztami. W idealnym przypadku aplikacja jest wystarczająco inteligentna, aby zrozumieć, które produkty uległy zmianie, i stopniowo aktualizować te strony bez konieczności pełnego przebudowy .

Więcej po skoku! Kontynuuj czytanie poniżej ↓

Przyrostowa regeneracja statyczna (ISR)

Next.js umożliwia tworzenie lub aktualizowanie stron statycznych po zbudowaniu witryny. Przyrostowa regeneracja statyczna (ISR) umożliwia programistom i edytorom treści korzystanie z generowania statycznego na podstawie każdej strony, bez konieczności przebudowywania całej witryny . Dzięki ISR ​​możesz zachować zalety statyczne i skalować do milionów stron.

Strony statyczne można generować w czasie wykonywania (na żądanie) zamiast w czasie kompilacji za pomocą ISR. Korzystając z analiz, testów A/B lub innych metryk, masz elastyczność, dzięki której możesz dokonać własnego kompromisu w zakresie czasu kompilacji.

Pomyśl o sklepie e-commerce sprzed 100 000 produktów. Przy realistycznym 50 ms generowania statycznego każdej strony produktu zajęłoby to prawie 2 godziny bez ISR . Dzięki ISR ​​mamy do wyboru:

  • Szybsze kompilacje
    Wygeneruj najpopularniejsze 1000 produktów w czasie budowy. Żądania kierowane do innych produktów będą powodować braki w pamięci podręcznej i statycznie generować na żądanie: 1-minutowe kompilacje.
  • Wyższy współczynnik trafień w pamięci podręcznej
    Generuj 10 000 produktów w czasie kompilacji, zapewniając buforowanie większej liczby produktów przed żądaniem użytkownika: kompilacje 8-minutowe.
Ilustracja przedstawiająca Jamstack po lewej stronie i przyrostową regenerację statyczną po prawej stronie
Zaleta ISR: masz elastyczność wyboru stron generowanych podczas kompilacji lub na żądanie. Wybierz spośród (A) szybszych kompilacji lub (B) bardziej buforowanych. (duży podgląd)

Przeanalizujmy przykład ISR dla strony produktu e-commerce.

Pierwsze kroki

Pobieranie danych

Jeśli nigdy wcześniej nie używałeś Next.js, polecam przeczytanie Pierwsze kroki z Next.js, aby zrozumieć podstawy. ISR używa tego samego API Next.js do generowania stron statycznych: getStaticProps . Określając revalidate: 60 , informujemy Next.js o użyciu ISR dla tej strony.

Schemat przepływu żądań dla przyrostowej regeneracji statycznej
Schemat przepływu żądań dla przyrostowej regeneracji statycznej. (duży podgląd)
  1. Next.js może zdefiniować czas ponownej walidacji na stronę. Ustawmy to na 60 sekund.
  2. Początkowe żądanie do strony produktu pokaże stronę z pamięci podręcznej z pierwotną ceną.
  3. Dane dla produktu są aktualizowane w CMS.
  4. Wszelkie żądania skierowane do strony po początkowym żądaniu i przed 60 sekundami są buforowane i natychmiastowe.
  5. Po 60-sekundowym oknie następne żądanie nadal będzie pokazywać stronę z pamięci podręcznej (nieaktualną). Next.js uruchamia regenerację strony w tle .
  6. Po pomyślnym wygenerowaniu strony Next.js unieważni pamięć podręczną i wyświetli zaktualizowaną stronę produktu. Jeśli regeneracja w tle nie powiedzie się, stara strona pozostanie niezmieniona.
 // pages/products/[id].js export async function getStaticProps({ params }) { return { props: { product: await getProductFromDatabase(params.id) }, revalidate: 60 } }

Generowanie ścieżek

Next.js określa, które produkty należy generować w czasie kompilacji, a które na żądanie. Wygenerujmy tylko 1000 najpopularniejszych produktów w czasie kompilacji, dostarczając getStaticPaths listę 1000 najpopularniejszych identyfikatorów produktów.

Musimy skonfigurować sposób, w jaki Next.js będzie „powracać” podczas żądania innych produktów po początkowej kompilacji. Do wyboru są dwie opcje: blocking i true .

  • fallback: blocking (preferowane)
    Gdy żądanie zostanie skierowane do strony, która nie została wygenerowana, Next.js wyrenderuje stronę przez serwer przy pierwszym żądaniu. Przyszłe żądania będą obsługiwać plik statyczny z pamięci podręcznej.
  • fallback: true
    Gdy żądanie zostanie skierowane do strony, która nie została wygenerowana, Next.js natychmiast wyświetli stronę statyczną ze stanem ładowania przy pierwszym żądaniu. Po zakończeniu ładowania danych strona zostanie ponownie wyrenderowana z nowymi danymi i zostanie zapisana w pamięci podręcznej. Przyszłe żądania będą obsługiwać plik statyczny z pamięci podręcznej.
 // 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' } }

Kompromisy

Next.js skupia się przede wszystkim na użytkowniku końcowym. „Najlepsze rozwiązanie” jest względne i różni się w zależności od branży, odbiorców i charakteru aplikacji. Pozwalając programistom na przełączanie się między rozwiązaniami bez opuszczania granic frameworka, Next.js pozwala wybrać odpowiednie narzędzie do projektu.

Renderowanie po stronie serwera

ISR nie zawsze jest właściwym rozwiązaniem. Na przykład kanał wiadomości na Facebooku nie może pokazywać nieaktualnej treści. W tym przypadku chciałbyś użyć SSR i potencjalnie własnych nagłówków cache-control z kluczami zastępczymi, aby unieważnić zawartość. Ponieważ Next.js jest frameworkiem hybrydowym, możesz dokonać tego kompromisu samodzielnie i pozostać w ramach frameworka.

 // 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 i buforowanie brzegowe są podobne do ISR (zwłaszcza w przypadku używania nagłówków pamięci podręcznej stale-while-revalidate ponownego sprawdzania poprawności), przy czym główną różnicą jest pierwsze żądanie. Dzięki ISR ​​pierwsze żądanie może być gwarantowane jako statyczne, jeśli jest wstępnie renderowane. Nawet jeśli Twoja baza danych ulegnie awarii lub wystąpi problem z komunikacją z interfejsem API, Twoi użytkownicy nadal będą widzieć prawidłowo obsługiwaną stronę statyczną. Jednak SSR pozwoli Ci dostosować stronę na podstawie przychodzącego żądania.

Uwaga : używanie SSR bez buforowania może prowadzić do niskiej wydajności. Każda milisekunda ma znaczenie podczas blokowania użytkownikowi dostępu do Twojej witryny, a to może mieć dramatyczny wpływ na TTFB (czas do pierwszego bajtu).

Generowanie stron statycznych

ISR nie zawsze ma sens w przypadku małych stron internetowych. Jeśli okres ponownej walidacji jest dłuższy niż czas potrzebny na odbudowanie całej witryny, równie dobrze możesz użyć tradycyjnego generowania witryn statycznych.

Renderowanie po stronie klienta

Jeśli używasz Reacta bez Next.js, korzystasz z renderowania po stronie klienta. Twoja aplikacja obsługuje stan ładowania, po którym następuje żądanie danych wewnątrz JavaScript po stronie klienta (np. useEffect ). Chociaż zwiększa to opcje hostingu (ponieważ nie jest potrzebny serwer), istnieją pewne kompromisy.

Brak wstępnie wyrenderowanej zawartości z początkowego kodu HTML prowadzi do wolniejszej i mniej dynamicznej optymalizacji pod kątem wyszukiwarek (SEO). Nie można również używać CSR z wyłączoną obsługą JavaScript.

Opcje awaryjne ISR

Jeśli Twoje dane można szybko pobrać, rozważ użycie fallback: blocking . Wtedy nie musisz brać pod uwagę stanu ładowania, a Twoja strona zawsze pokaże ten sam wynik (bez względu na to, czy jest zapisana w pamięci podręcznej, czy nie). Jeśli pobieranie danych jest powolne, funkcja fallback: true umożliwia natychmiastowe wyświetlenie użytkownikowi stanu ładowania.

ISR: Nie tylko buforowanie!

Chociaż wyjaśniłem ISR w kontekście pamięci podręcznej, jest on przeznaczony do utrwalania wygenerowanych stron między wdrożeniami. Oznacza to, że możesz natychmiast cofnąć się i nie stracić wcześniej wygenerowanych stron.

Każde wdrożenie może być poprzedzone identyfikatorem, którego Next.js używa do utrwalania stron generowanych statycznie. Po wycofaniu można zaktualizować klucz, aby wskazywał na poprzednie wdrożenie, umożliwiając wdrożenia atomowe. Oznacza to, że możesz odwiedzić poprzednie niezmienne wdrożenia i będą one działać zgodnie z przeznaczeniem.

  • Oto przykład przywracania kodu za pomocą ISR:
  • Wypychasz kod i otrzymujesz identyfikator wdrożenia 123.
  • Twoja strona zawiera literówkę „Smshng Magazine”.
  • Aktualizujesz stronę w CMS. Nie ma potrzeby ponownego wdrażania.
  • Gdy na Twojej stronie pojawi się „Smashing Magazine”, jest on przechowywany w pamięci.
  • Wciskasz zły kod i wdrażasz ID 345.
  • Wracasz do wdrożenia identyfikatora 123.
  • Nadal widzisz „Smashing Magazine”.

Przywraca i utrzymujące się strony statyczne są poza zakresem Next.js i zależą od dostawcy hostingu. Zauważ, że ISR różni się od renderowania przez serwer z nagłówkami Cache-Control , ponieważ z założenia pamięci podręczne wygasają. Nie są one współdzielone w różnych regionach i zostaną wyczyszczone po przywróceniu.

Przykłady przyrostowej regeneracji statycznej

Przyrostowa regeneracja statyczna działa dobrze w przypadku e-commerce, stron marketingowych, postów na blogach, mediów z reklamami i nie tylko.

  • Demo e-commerce
    Next.js Commerce to uniwersalny zestaw startowy dla wydajnych witryn e-commerce.
  • Demo reakcji na GitHub
    Zareaguj na oryginalny problem z GitHub i zobacz, jak ISR aktualizuje statycznie wygenerowaną stronę docelową.
  • Demo statycznych tweetów
    Ten projekt jest wdrażany w 30 sekund, ale może statycznie generować 500 milionów tweetów na żądanie za pomocą ISR.

Dowiedz się Next.js już dziś

Deweloperzy i duże zespoły wybierają Next.js ze względu na jego hybrydowe podejście i możliwość przyrostowego generowania stron na żądanie. Dzięki ISR ​​zyskujesz korzyści statyczne z elastycznością renderowania serwerowego. ISR działa po wyjęciu z pudełka, używając next start .

Next.js został zaprojektowany z myślą o stopniowym przyjmowaniu. Dzięki Next.js możesz nadal korzystać z istniejącego kodu i dodawać tyle (lub tak mało) React, ile potrzebujesz. Zaczynając od małych i stopniowo dodając więcej stron, możesz zapobiec wykolejeniu pracy funkcji, unikając całkowitego przepisywania. Dowiedz się więcej o Next.js — życzę wszystkim miłego kodowania!

Dalsza lektura

  • Pierwsze kroki z Next.js
  • Porównanie metod stylizacji w Next.js
  • Jak zbudować serwer GraphQL przy użyciu tras API Next.js?