Dowiedz się, jak przyspieszyć działanie aplikacji Next.js przez podział kodu i strategie inteligentnego wczytywania.
Czego się nauczysz?
W tym poście opisujemy różne typy dzielenia kodu oraz sposoby wykorzystywania dynamicznego importu do przyspieszenia działania aplikacji Next.js.
Podział kodu na podstawie trasy i komponentu
Domyślnie Next.js dzieli JavaScript na osobne fragmenty dla każdej trasy. Gdy użytkownicy ładują Twoją aplikację, Next.js wysyła tylko kod niezbędny dla trasy początkowej. Gdy użytkownicy poruszają się po aplikacji, pobierają fragmenty powiązane z innymi trasami. Dzielenie kodu na podstawie tras minimalizuje liczbę skryptów, które muszą być jednocześnie analizowane i skompilowane, co skraca czas wczytywania strony.
Dzielenie kodu na podstawie trasy jest dobrym ustawieniem domyślnym, ale można dodatkowo zoptymalizować proces wczytywania za pomocą podziału kodu na poziomie komponentu. Jeśli masz w aplikacji duże komponenty, warto je podzielić na osobne części. Dzięki temu wszystkie duże komponenty, które nie mają kluczowego znaczenia lub są renderowane tylko w przypadku określonych interakcji użytkownika (np. kliknięcia przycisku), mogą być ładowane leniwie.
Next.js obsługuje dynamiczny import()
,
co pozwala dynamicznie importować moduły JavaScript (w tym komponenty React)
i ładować każdy import jako oddzielny fragment. Pozwala to podzielić kod na poziomie komponentu i kontrolować wczytywanie zasobów, aby użytkownicy pobierali tylko ten kod, którego potrzebują do danej części witryny, którą przeglądają. W Next.js komponenty te są domyślnie renderowane po stronie serwera (SSR).
Importowanie dynamiczne w praktyce
Ten post zawiera kilka wersji przykładowej aplikacji, która składa się z prostej strony z 1 przyciskiem. Po kliknięciu przycisku zobaczysz uroczego szczeniaka. W trakcie poruszania się po kolejnych wersjach aplikacji nauczysz się, czym importowanie dynamiczne różni się od importów statycznych, i jak korzystać z nich.
W pierwszej wersji aplikacji szczeniak mieszka w tym kraju: components/Puppy.js
. Aby wyświetlić szczeniaka na stronie, aplikacja importuje komponent Puppy
w index.js
za pomocą statycznej instrukcji importu:
import Puppy from "../components/Puppy";
Aby zobaczyć, jak Next.js pakuje aplikację, sprawdź śledzenie sieci w Narzędziach deweloperskich:
Aby wyświetlić podgląd strony, kliknij Wyświetl aplikację, a potem Pełny ekran .
Naciśnij „Control + Shift + J” (lub „Command + Option + J” na Macu), aby otworzyć Narzędzia deweloperskie.
Kliknij kartę Sieć.
Zaznacz pole wyboru Wyłącz pamięć podręczną.
Odśwież stronę.
Po załadowaniu strony cały niezbędny kod, w tym komponent Puppy.js
, jest umieszczony w pakiecie index.js
:
Gdy naciśniesz przycisk Kliknij mnie, do karty Sieć zostanie dodana tylko prośba o włączenie pliku JPEG szczeniaka:
Wadą tego podejścia jest to, że nawet jeśli użytkownik nie kliknie przycisku, aby zobaczyć szczeniaka, będzie musiał załadować komponent Puppy
, ponieważ zawiera on komponent index.js
. W tym przykładzie to nie jest wielki problem, ale w rzeczywistych zastosowaniach często okazuje się, że duże komponenty można wczytywać tylko wtedy, gdy jest to konieczne.
Teraz zapoznaj się z drugą wersją aplikacji, w której import statyczny został zastąpiony przez import dynamiczny. Next.js zawiera obiekt next/dynamic
, który umożliwia stosowanie dynamicznego importowania dla dowolnych komponentów w sekcji Next:
import Puppy from "../components/Puppy";
import dynamic from "next/dynamic";
// ...
const Puppy = dynamic(import("../components/Puppy"));
Wykonaj czynności z pierwszego przykładu, aby zbadać śledzenie sieci.
Przy pierwszym wczytaniu aplikacji pobierana jest tylko index.js
. Tym razem jest on mniejszy o 0,5 KB (zmniejszył się z 37,9 KB do 37,4 KB), ponieważ nie zawiera kodu komponentu Puppy
:
Komponent Puppy
znajduje się teraz w osobnym fragmencie (1.js
), który jest ładowany dopiero po naciśnięciu przycisku:
W rzeczywistych zastosowaniach komponenty są często znacznie większe, a leniwe ładowanie ich może skrócić początkowy ładunek JavaScript o setki kilobajtów.
Dynamiczne importy z niestandardowym wskaźnikiem wczytywania
W przypadku leniwego ładowania zasobów warto udostępnić wskaźnik ładowania w przypadku opóźnień. W Next.js możesz to zrobić, podając dodatkowy argument do funkcji dynamic()
:
const Puppy = dynamic(() => import("../components/Puppy"), {
loading: () => <p>Loading...</p>
});
Aby zobaczyć, jak działa wskaźnik ładowania, wykonaj symulację wolnego połączenia sieciowego w Narzędziach deweloperskich:
Aby wyświetlić podgląd strony, kliknij Wyświetl aplikację, a potem Pełny ekran .
Naciśnij „Control + Shift + J” (lub „Command + Option + J” na Macu), aby otworzyć Narzędzia deweloperskie.
Kliknij kartę Sieć.
Zaznacz pole wyboru Wyłącz pamięć podręczną.
Z listy Ograniczanie wybierz Szybka 3G.
Naciśnij przycisk Kliknij mnie.
Gdy klikniesz przycisk, wczytanie komponentu zajmie trochę czasu, a aplikacja wyświetli komunikat „Wczytuję...”.
Dynamiczne importy bez SSR
Jeśli chcesz renderować komponent tylko po stronie klienta (np. widżet czatu), możesz ustawić opcję ssr
na false
:
const Puppy = dynamic(() => import("../components/Puppy"), {
ssr: false,
});
Podsumowanie
Dzięki obsłudze importowania dynamicznego Next.js umożliwia dzielenie kodu na poziomie komponentu, co może zminimalizować ładunki JavaScript i skrócić czas wczytywania aplikacji. Wszystkie komponenty są domyślnie renderowane po stronie serwera i w razie potrzeby możesz wyłączyć tę opcję.