W ostatnim czasie NextJS zyskuje coraz większą popularność jako sposób na tworzenie aplikacji React. Z pewnością duży wpływ na to ma fakt, że NextJS oferuje kilka różnych strategii pobierania danych.
A są to:
Renderowanie po stronie klienta: CSR,
Renderowanie po stronie serwera: SSR,
Statyczne renderowanie strony: SSG,
Przyrostowa regeneracja statyczna: ISR.
NextJS, w przeciwieństwie do zwykłej aplikacji React, oferuje funkcję zwaną pre-renderowaniem. Oznacza to, że wstępnie renderowany HTML jest wyświetlany podczas początkowego ładowania. W tradycyjnych aplikacjach React cała aplikacja jest ładowana i renderowana po stronie klienta. Następnie, po załadowaniu JS kod aplikacja staje się interaktywna.
Generacja statyczna
W SSG HTML jest generowany w czasie kompilacji i ponownie wykorzystywany dla każdego żądania. Po utworzeniu kompilacji produkcyjnej każde żądanie będzie ponownie wykorzystywać ten statycznie wygenerowany plik HTML.
Istnieją również dwa rodzaje generowania statycznego: z danymi i bez danych.
W pierwszym przypadku HTML zostanie wygenerowany po pobraniu danych przez rozwiązanie obietnicy. W tym przypadku możemy użyć metody pobierania danych getStaticProps... ale tylko jeśli używasz Next.js 9.3 lub nowszego. Jeśli nie, pomyśl o aktualizacji, ponieważ starsza metoda getInitialProps nie jest już zalecana i będzie przestarzała. Metoda ta jest również wywoływana w każdej nawigacji po stronie klienta, więc nie jest wydajna, jeśli nie chcesz pobierać danych przy każdym żądaniu.
Naprawdę fajną rzeczą jest nowo wydana funkcja o nazwie ISR (Incremental Static Regeneration), która jest czymś pomiędzy SSG i SSR. Pozwala ona (przy użyciu określonego klucza o nazwie revalidate) na przyrostową regenerację strony. Oznacza to, że dzięki temu kluczowi nie trzeba przebudowywać aplikacji za każdym razem, gdy chcemy uzyskać aktualizację danych pobranych z serwera. Wystarczy dodać klucz revalidate z okresem rewalidacji w sekundach.
Oznacza to, że jeśli żądanie nadejdzie po tym okresie, to ponownie pobierze dane z serwera.
Inną sytuacją jest użycie dynamicznej strony, której ścieżka zależy od zewnętrznych danych. W takim przypadku możemy użyć metody getStaticPaths informującej, które trasy dynamiczne powinny zostać wstępnie załadowane:
export async const getStaticProps = ({ params }) => {
const res = await fetch(`https://jsonplaceholder.typicode.com/posts/${params.id}`);
const post = await res.json();
return {
props: { post },
};
}
Istnieje dobry sposób na sprawdzenie, które trasy dynamiczne zostały utworzone. Możesz uruchomić następną kompilację i następny eksport, a następnie będziesz mieć statyczną wersję swojej aplikacji w nowo utworzonym katalogu out.
Po uruchomieniu kolejnego eksportu możemy zauważyć w obu przypadkach (z i bez ograniczonej liczby ścieżek) różną liczbę postów znalezionych w my-appoutposts.
Przyjrzyjmy się teraz bliżej kluczowemu i wymaganemu parametrowi awaryjnemu. Mówi on, co zrobić, jeśli strona nie została wstępnie renderowana w czasie kompilacji. Jeśli jest ustawiony na true, getStaticProps uruchamia i generuje tę stronę. Jeśli false, otrzymamy 404 po próbie załadowania tej konkretnej ścieżki. Kolejna rzecz: strony z fallback, które są włączone w getStaticPaths nie mogą być eksportowane.
Poniżej znajdują się wyniki próby załadowania tej samej strony dynamicznej w obu przypadkach:
Pierwszy przypadek (bez ograniczonych ścieżek)
Drugi przypadek (z ograniczonymi ścieżkami i ustawieniem awaryjnym na false)
Drugi przypadek (z ograniczonymi ścieżkami i ustawieniem awaryjnym na true)
Renderowanie po stronie serwera
Główna różnica w stosunku do SSG: nowy HTML jest generowany przy każdym żądaniu. Jest używany głównie wtedy, gdy pobieramy dane zewnętrzne. W takim przypadku nie ma potrzeby przebudowywania aplikacji za każdym razem, gdy chcemy zaktualizować dane z serwera.
Metoda getServerSideProps wygląda bardzo podobnie do getStaticProps. Różnica polega na tym, że getServerSideProps działa przy każdym żądaniu, podczas gdy getStaticProps działa raz w czasie kompilacji.
Renderowanie po stronie klienta
W przypadku renderowania po stronie klienta początkowe ładowanie strony jest nieco powolne. Komunikacja z serwerem odbywa się w czasie wykonywania. Można to zrobić w bardziej tradycyjny sposób:
Możemy również skorzystać z innego rozwiązania, 'swr' - React Hooks library for data fetching by Vercel*, które jest mocno rekomendowane przez twórców NextJS. SWR to skrót od State While Revalidate.
import useSWR from "swr";
const Blog = () => {
const fetcher = (url) => fetch(url).then((r) => r.json());
const { data: posts = [], error } = useSWR(
"https://jsonplaceholder.typicode.com/posts", fetcher);
if (error) return <div>Nie udało się załadować postów</div>;
if (!posts.length) return <div>ładowanie...</div>;
return (
<>
{posts.map((post) => (
{post.title}
))}
</>
}
Podsumowanie
NextJS gives us the additional possibility of choosing which of the data fetching strategies we want to use on each page. We don’t need to follow only one solution for the whole application.
Skrót
getServerSideProps - gdy trzeba wstępnie wyrenderować aplikację przy każdym żądaniu z pobranymi danymi
getStaticProps - gdy dane mogą być pobierane raz w czasie kompilacji i używane przy każdym żądaniu bez aktualizacji
getInitialProps - niezalecane, będzie przestarzałe
getStaticPaths - do wstępnego renderowania ścieżek dynamicznych