Korzystanie z haków SWR React z przyrostową regeneracją statyczną Next.js (ISR)
Opublikowany: 2022-03-10Jeśli kiedykolwiek używałeś Incremental Static Regeneration (ISR) z Next.js, być może zdarzyło Ci się wysyłać przestarzałe dane do klienta. Dzieje się tak, gdy ponownie weryfikujesz stronę na serwerze. W przypadku niektórych witryn to działa, ale w przypadku innych (takich jak Scrapbook Hack Club, witryna zbudowana przez @lachlanjc, którą pomagam w utrzymaniu), użytkownik oczekuje, że dane będą aktualizowane.
Pierwszym rozwiązaniem, które przychodzi do głowy, może być po prostu renderowanie stron po stronie serwera, dzięki czemu klient otrzymuje zawsze najbardziej aktualne dane. Jednak pobieranie dużych porcji danych przed renderowaniem może spowolnić początkowe ładowanie strony. Rozwiązaniem zastosowanym w Scrapbooku było wykorzystanie biblioteki SWR podpięć React do aktualizacji strony z pamięci podręcznej z serwera z pobieraniem danych po stronie klienta . Takie podejście gwarantuje, że użytkownicy nadal będą mieli dobre wrażenia, że witryna jest szybka, a dane są aktualizowane.
Poznaj SWR
SWR to biblioteka React Hooks zbudowana przez Vercel, nazwa pochodzi od terminu „przestarzały podczas ponownego sprawdzania poprawności”. Jak sama nazwa wskazuje, Twój klient będzie obsługiwany nieaktualnymi/starymi danymi, podczas gdy najbardziej aktualne dane będą pobierane (ponowne sprawdzanie) przez SWR po stronie klienta. SWR nie tylko raz weryfikuje dane, jednak możesz skonfigurować SWR tak, aby ponownie weryfikował dane co jakiś czas, gdy karta odzyska fokus, gdy klient ponownie połączy się z Internetem lub programowo.
W połączeniu z trasami ISR i Next.js API, SWR może być używany do tworzenia responsywnych doświadczeń użytkownika . Klientowi najpierw jest serwowana zbuforowana statycznie wygenerowana strona (wygenerowana za pomocą getStaticProps()
), w tle serwer również rozpoczyna proces ponownej walidacji tej strony (czytaj więcej tutaj). Ten proces jest szybki dla klienta i może teraz zobaczyć zestaw danych, jednak może to być trochę nieaktualne. Po załadowaniu strony wysyłane jest żądanie pobrania do Twojej trasy API Next.js, która zwraca te same dane, które zostały wygenerowane za pomocą getStaticProps()
. Po zakończeniu tego żądania (zakładając, że zakończyło się powodzeniem), SWR zaktualizuje stronę o nowe dane.
Spójrzmy teraz wstecz na Notatnik i jak to pomogło rozwiązać problem z nieaktualnymi danymi na stronie . Oczywiste jest, że teraz klient otrzymuje zaktualizowaną wersję. Bardziej interesującą rzeczą jest jednak wpływ na szybkość naszej strony. Kiedy mierzymy prędkość przez Lighthouse, otrzymujemy indeks prędkości 1,5 sekundy dla wariantu witryny ISR + SWR i 5,8 sekundy dla wariantu renderowania po stronie serwera (plus ostrzeżenie dotyczące początkowego czasu odpowiedzi serwera). To dość wyraźny kontrast między tymi dwoma (i było to również zauważalne podczas ładowania stron). Ale jest też kompromis, na stronie Server Side Rendered użytkownik nie zmienił układu witryny po kilku sekundach z nadejściem nowych danych. Chociaż uważam, że Scrapbook dobrze radzi sobie z tą aktualizacją, jest to ważne, gdy projektowanie doświadczenia użytkownika.
Gdzie używać SWR (a gdzie nie)
SWR można umieścić w różnych miejscach, oto kilka kategorii witryn, w których SWR doskonale pasuje:
- Witryny z danymi na żywo, które wymagają szybkiej aktualizacji.
Przykładami takich witryn są witryny z wynikami sportowymi i śledzenie lotów. Tworząc te witryny, warto skorzystać z opcji Ponowna walidacja w interwale z ustawieniem niskiego interwału (od jednej do pięciu sekund). - Witryny ze stylem kanału aktualizacji lub postów, które są aktualizowane w czasie rzeczywistym.
Klasycznym przykładem mogą być serwisy informacyjne, które prowadzą na żywo blogi o wydarzeniach takich jak wybory. Innym przykładem może być wspomniany wcześniej Scrapbook. W takim przypadku prawdopodobnie zechcesz również użyć opcji rewalidacji w interwale, ale z wyższym ustawieniem interwału (od trzydziestu do sześćdziesięciu sekund), aby zaoszczędzić na zużyciu danych i zapobiec niepotrzebnym wywołaniom interfejsu API. - Witryny z bardziej pasywnymi aktualizacjami danych, które ludzie często otwierają w tle.
Przykładami takich witryn mogą być strony z pogodą lub strony z numerami spraw COVID-19 z lat 2020. Te strony nie są aktualizowane tak często, a zatem nie wymagają ciągłego weryfikowania poprzednich dwóch przykładów. Jednak aktualizacja danych nadal poprawiłaby komfort użytkownika. W takich przypadkach sugerowałbym ponowne sprawdzenie daty, w której karta odzyska koncentrację i gdy klient ponownie połączy się z Internetem, będzie to oznaczać, że dana osoba z niepokojem wróci do kranu z nadzieją, że nastąpił tylko niewielki wzrost przypadków COVID. szybko uzyskać te dane. - Witryny z małymi fragmentami danych, z którymi użytkownicy mogą wchodzić w interakcje.
Pomyśl o przycisku subskrypcji YouTube, kiedy klikniesz subskrybuj, chcesz zobaczyć zmianę liczby i poczuć, jak coś zmieniłeś. W takich przypadkach można ponownie zweryfikować dane programowo za pomocą SWR, aby pobrać nową liczbę i zaktualizować wyświetlaną ilość.
Należy zauważyć, że wszystkie mogą być stosowane z lub bez ISR.
Są oczywiście miejsca, w których nie będziesz chciał używać SWR lub używać SWR bez ISR. SWR nie jest zbyt przydatny, jeśli dane nie zmieniają się lub zmieniają się bardzo rzadko, a zamiast tego mogą blokować żądania sieciowe i wykorzystywać dane użytkowników mobilnych. SWR może pracować ze stronami wymagającymi uwierzytelnienia, jednak w takich przypadkach będziesz chciał użyć renderowania po stronie serwera, a nie przyrostowej regeneracji statycznej.
Używanie SWR z Next.js i przyrostową regeneracją statyczną
Teraz zbadaliśmy teorię tej strategii, przyjrzyjmy się, jak stosujemy ją w praktyce. W tym celu zbudujemy stronę internetową, która pokazuje, ile taksówek jest dostępnych w Singapurze (gdzie mieszkam!) przy użyciu tego interfejsu API dostarczonego przez rząd.
Struktura projektu
Nasz projekt będzie działał dzięki posiadaniu trzech plików:
-
lib/helpers.js
-
pages/index.js
(nasz plik frontendowy) -
pages/api/index.js
(nasz plik API)
Nasz plik pomocniczy wyeksportuje funkcję ( getTaxiData
), która pobierze dane z zewnętrznego API, a następnie zwróci je w odpowiednim formacie do naszego użytku. Nasz plik API zaimportuje tę funkcję i ustawi jej domyślny eksport na funkcję obsługi, która wywoła funkcję getTaxiData
, a następnie ją zwróci, co będzie oznaczać, że wysłanie żądania GET do /api
zwróci nasze dane.
Będziemy potrzebować tej możliwości, aby SWR mógł pobierać dane po stronie klienta. Na koniec w naszym pliku frontendowym zaimportujemy getTaxiData
i użyjemy ich w getStaticProps
, jego dane zostaną przekazane do domyślnej funkcji eksportu naszego pliku frontendowego, który wyrenderuje naszą stronę React. Robimy to wszystko, aby zapobiec powielaniu kodu i zapewnić spójność naszych danych. Co za kęs, zacznijmy teraz programować.
Plik pomocników
Zaczniemy od stworzenia funkcji getTaxiData
w 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} }
Plik API
Następnie zbudujemy funkcję obsługi w api/index.js
oraz zaimportujemy funkcję getTaxiData
:
import { getTaxiData } from '../../lib/helpers' export default async function handler(req, res){ res.status(200).json(await getTaxiData()) }
Nie ma tu nic unikalnego dla SWR czy ISR, poza wspomnianą strukturą projektu. To zaczyna się teraz w index.js
!
Plik frontonu
Pierwszą rzeczą, którą chcemy zrobić, to stworzyć naszą funkcję getStaticProps
! Ta funkcja zaimportuje naszą funkcję getTaxiData
, użyje jej, a następnie zwróci dane z dodatkową konfiguracją.
export async function getStaticProps(){ const { getTaxiData } = require("../lib/helpers") return { props: (await getTaxiData()), revalidate: 1 } }
Chciałbym skupić się na kluczu rewalidacji w naszym zwróconym obiekcie. Ten klucz praktycznie umożliwia przyrostową regenerację statyczną. Informuje hosta, że co sekundę regenerowanie strony statycznej jest dostępną opcją, która jest następnie uruchamiana w tle, gdy klient odwiedza Twoją stronę. Możesz przeczytać więcej o przyrostowej regeneracji statycznej (ISR) tutaj.
Nadszedł czas na użycie SWR! Najpierw zaimportujmy:
import useSWR from 'swr'
Będziemy używać SWR w naszej funkcji renderowania React, więc stwórzmy tę funkcję:
export default function App(props){ }
Rekwizyty otrzymujemy z getStaticProps
. Teraz jesteśmy gotowi do skonfigurowania SWR:
const fetcher = (...args) => fetch(...args).then(res => res.json()) const { data } = useSWR("/api", fetcher, {fallbackData: props, refreshInterval: 30000})
Rozłóżmy to. Po pierwsze, definiujemy moduł pobierania. Jest to wymagane przez SWR jako argument, aby wiedział, jak pobrać dane, biorąc pod uwagę, że różne frameworki itp. mogą mieć różne konfiguracje. W tym przypadku korzystam z funkcji udostępnionej na stronie dokumentów SWR. Następnie wywołujemy hak useSWR
z trzema argumentami: ścieżką, z której pobierane są dane, funkcją pobierającą, a następnie obiektem opcji.
W tym obiekcie options
określiliśmy dwie rzeczy:
- dane awaryjne;
- Interwał, w którym SWR powinien ponownie zweryfikować dane.
Opcja danych rezerwowych to miejsce, w którym dostarczamy dane pobrane z getStaticProps
, co zapewnia, że dane są widoczne od samego początku. Na koniec używamy destrukturyzacji obiektów, aby wyodrębnić dane z haka.
Na koniec wyrenderujemy te dane za pomocą bardzo podstawowego JSX:
return <div>As of {data.updatedAt}, there are {data.taxis} taxis available in Singapore!</div>
I zrobiliśmy to! Mamy bardzo prosty przykład wykorzystania SWR z przyrostową regeneracją statyczną. (Źródło naszego przykładu jest dostępne tutaj.)
Jeśli kiedykolwiek natkniesz się na nieaktualne dane z ISR, wiesz, do kogo zadzwonić: SWR.
Dalsze czytanie na SmashingMag
- Biblioteka haków SWR React
- Wprowadzenie do SWR: React Hooks do zdalnego pobierania danych, Ibrahima Ndaw
- ISR kontra DPR: wielkie słowa, szybkie wyjaśnienie, Cassidy Williams
- Stylizacja globalna a lokalna w Next.js, Alexander Dubovoj
- Routing po stronie klienta w Next.js, Adebiyi Adedotun Lukman