Wstępne pobieranie tras w Next.js

Jak Next.js przyspiesza nawigację dzięki wstępnemu pobieraniu tras i jak go dostosować.

Czego się nauczysz?

Z tego posta dowiesz się, jak działa routing w Next.js, jak jest on optymalizowany pod kątem szybkości oraz jak możesz go dostosować do swoich potrzeb.

W przypadku kodu Next.js nie musisz ręcznie konfigurować routingu. Next.js korzysta z przekierowywania opartego na systemie plików, co pozwala na tworzenie plików i folderów w katalogu ./pages/:

Zrzut ekranu pokazujący katalog stron zawierający 3 pliki: index.js, margherita.js i pineapple-pizza.js

Aby utworzyć link do różnych stron, użyj komponentu <Link> w podobny sposób jak starego elementu <a>:

<Link href="/margherita">
  <a>Margherita</a>
</Link>

Gdy używasz komponentu <Link> do nawigacji, Next.js robi dla Ciebie nieco więcej. Normalnie strona jest pobierana, gdy klikniesz link do niej, ale Next.js automatycznie pobiera z wyprzedzeniem kod JavaScript potrzebny do wyrenderowania strony.

Gdy wczytasz stronę z kilkoma linkami, istnieje duże prawdopodobieństwo, że do czasu kliknięcia linku komponent, do którego prowadzi, został już pobrany. Dzięki temu aplikacja będzie szybciej reagować na Twoje działania, ponieważ szybciej będzie się przełączać na nowe strony.

W przykładowej aplikacji poniżej strona index.js zawiera link do strony margherita.js z użyciem <Link>:

Użyj Narzędzi deweloperskich w Chrome, aby sprawdzić, czy margherita.js jest pobierane z poziomu pamięci podręcznej: 1. Aby wyświetlić podgląd strony, kliknij Wyświetl aplikację. Następnie kliknij Pełny ekranpełny ekran.

  1. Naciśnij „Control + Shift + J” (lub „Command + Option + J” na Macu), aby otworzyć Narzędzia deweloperskie.
  2. Kliknij kartę Sieć.

  3. Zaznacz pole wyboru Wyłącz pamięć podręczną.

  4. Odśwież stronę.

Gdy wczytasz index.js, na karcie Sieć widać, że margherita.js została też pobrana:

Karta Sieć w Narzędziach deweloperskich z wyróżnionym plikiem margherita.js

Jak działa automatyczne pobieranie wstępne

Next.js pobiera w poprzednim ładowaniu tylko linki, które pojawiają się w widoku, i wykorzystuje do ich wykrywania interfejs IntersectionObserver API. Wyłącza też pobieranie z wyprzedzeniem, gdy połączenie sieciowe jest wolne lub gdy użytkownicy mają włączoną Save-Data. Na podstawie tych kontroli Next.js dynamicznie wstrzykuje tagi <link rel="preload">, aby pobrać komponenty na potrzeby kolejnych nawigacji.

Next.js tylko pobiera kod JavaScript, ale go nie wykonuje. Dzięki temu nie pobiera żadnych dodatkowych treści, których może wymagać strona z zapasowym wczytaniem, dopóki nie klikniesz linku.

Unikaj niepotrzebnego wstępnego pobierania

Aby uniknąć pobierania niepotrzebnych treści, możesz wyłączyć wstępne pobieranie w przypadku rzadko odwiedzanych stron, ustawiając w elementach prefetch w elementach <Link> wartość false:

<Link href="/pineapple-pizza" prefetch={false}>
  <a>Pineapple pizza</a>
</Link>

W tej drugiej przykładowej aplikacji strona index.js zawiera element <Link>, który prowadzi do strony pineapple-pizza.js, a element prefetch ma wartość false:

Aby sprawdzić aktywność sieciową, wykonaj czynności podane w pierwszym przykładzie. Gdy wczytasz index.js, na karcie Sieć w Narzędziach deweloperskich widać, że plik margherita.js został pobrany, ale pineapple-pizza.js nie:

Karta Sieć w Narzędziach deweloperskich z wyróżnionym plikiem margherita.js

Pobieranie w poprzedniości z użyciem trasy niestandardowej

Komponent <Link> nadaje się do większości przypadków użycia, ale możesz też utworzyć własny komponent do zarządzania routingiem. Next.js ułatwia to dzięki interfejsowi router API dostępnemu w next/router. Jeśli chcesz coś zrobić (np. przesłać formularz) przed przejściem na nową trasę, możesz to zdefiniować w niestandardowym kodzie kierowania.

Jeśli do routingu używasz komponentów niestandardowych, możesz też dodać do nich pobieranie z wyprzedzeniem. Aby zaimplementować funkcję wstępnego pobierania w kodzie kierowania, użyj metody prefetch z useRouter.

W tej przykładowej aplikacji components/MyLink.js:

Wstępne pobieranie odbywa się w ramach haka useEffect. Jeśli właściwość prefetch obiektu <MyLink> ma wartość true, trasa określona we właściwości href jest pobierana wstępnie podczas renderowania obiektu <MyLink>:

useEffect(() => {
    if (prefetch) router.prefetch(href)
});

Gdy klikniesz link, routing zostanie zakończony w aplikacji handleClick. W konsoli odnotowywany jest komunikat, a metoda push przechodzi do nowej ścieżki określonej w metodzie href:

const handleClick = e => {
    e.preventDefault();
    console.log("Having fun with Next.js.");
    router.push(href);
};

W tej przykładowej aplikacji strona index.js ma element <MyLink>, który prowadzi do elementów margherita.jspineapple-pizza.js. Właściwość prefetch ma wartość true w /margherita i false w /pineapple-pizza.

<MyLink href="/margherita" title="Margherita" prefetch={true} />
<MyLink href="/pineapple-pizza"  title="Pineapple pizza" prefetch={false} />

Gdy wczytasz index.js, na karcie Sieć widać, że plik margherita.js został pobrany, a plik pineapple-pizza.js nie:

Karta Sieć w Narzędziach deweloperskich z wyróżnionym plikiem margherita.js

Gdy klikniesz jeden z tych linków, Konsola zapisze w logach „Having fun with Next.js” i przejdzie do nowej ścieżki:

Konsole Narzędzi deweloperskich wyświetlająca komunikat „Having fun with Next.js”.

Podsumowanie

Gdy używasz tagu <Link>, Next.js automatycznie pobiera z wyprzedzeniem kod JavaScript potrzebny do renderowania połączonej strony, co przyspiesza otwieranie nowych stron. Jeśli używasz niestandardowego routingu, możesz samodzielnie wdrożyć pobieranie z wyprzedzeniem za pomocą interfejsu API routera Next.js. Aby uniknąć niepotrzebnego pobierania treści, wyłącz prefetching w przypadku rzadko odwiedzanych stron.