Ćwiczenia z programowania: wstępne wczytywanie zasobów krytycznych, które pozwalają przyspieszyć wczytywanie

W tym laboratorium kodowania poprawimy wydajność tej strony internetowej, wczytując wstępnie i pobierając z wyprzedzeniem kilka zasobów:

Zrzut ekranu aplikacji

Pomiary

Najpierw zmierz skuteczność witryny, zanim wprowadzisz jakiekolwiek optymalizacje.

  • Aby wyświetlić podgląd strony, kliknij Wyświetl aplikację, a następnie Pełny ekran pełny ekran.

Przeprowadź audyt wydajności za pomocą narzędzia Lighthouse (Lighthouse > Opcje > Wydajność) w przypadku wersji na żywo projektu Glitch (zobacz też Odkrywanie możliwości poprawy wydajności za pomocą narzędzia Lighthouse).

W przypadku zasobu pobranego z opóźnieniem narzędzie Lighthouse wyświetla ten nieudany test:

Lighthouse: audyt wstępnego wczytywania żądań kluczy
  • Aby otworzyć Narzędzia dla programistów, naciśnij Ctrl+Shift+J (lub Command+Option+J na Macu).
  • Kliknij kartę Sieć.
Panel sieci z późno wykrytym zasobem

Plik main.css nie jest pobierany przez element Link (<link>) umieszczony w dokumencie HTML, ale oddzielny plik JavaScript fetch-css.js dołącza element Link do DOM po zdarzeniu window.onLoad. Oznacza to, że plik jest pobierany dopiero po zakończeniu analizowania i wykonywania pliku JS przez przeglądarkę. Podobnie czcionka internetowa (K2D.woff2) określona w main.css jest pobierana dopiero po zakończeniu pobierania pliku CSS.

Łańcuch żądań krytycznych przedstawia kolejność zasobów, które są priorytetowo ładowane przez przeglądarkę. W przypadku tej strony internetowej wygląda to obecnie tak:

├─┬ / (initial HTML file)
  └── fetch-css.js
    └── main.css
      └── K2D.woff2

Ponieważ plik CSS znajduje się na trzecim poziomie łańcucha żądań, Lighthouse uznał go za zasób wykryty z opóźnieniem.

Wstępne wczytywanie najważniejszych zasobów

Plik main.css jest kluczowym zasobem, który jest potrzebny natychmiast po wczytaniu strony. W przypadku ważnych plików, takich jak ten zasób, które są pobierane w aplikacji z opóźnieniem, użyj tagu wstępnego wczytywania linku, aby poinformować przeglądarkę o wcześniejszym pobraniu pliku. W tym celu dodaj element Link do sekcji head dokumentu.

Dodaj tag wstępnego wczytywania dla tej aplikacji:

<head>
  <!-- ... -->
  <link rel="preload" href="main.css" as="style">
</head>

Atrybut as służy do określania typu pobieranego zasobu, a atrybut as="style" służy do wstępnego wczytywania plików arkusza stylów.

Załaduj ponownie aplikację i sprawdź panel Sieć w Narzędziach deweloperskich.

Panel sieci z wstępnie wczytanym zasobem

Zwróć uwagę, że przeglądarka pobiera plik CSS, zanim zakończy się parsowanie kodu JavaScript odpowiedzialnego za jego pobranie. W przypadku wczytywania wstępnego przeglądarka wie, że ma pobrać zasób z wyprzedzeniem, zakładając, że jest on kluczowy dla strony internetowej.

Nieprawidłowe użycie wstępnego wczytywania może pogorszyć wydajność, ponieważ spowoduje wysyłanie niepotrzebnych żądań dotyczących zasobów, które nie są używane. W tej aplikacji details.css to kolejny plik CSS znajdujący się w katalogu głównym projektu, ale używany do osobnego /details route. Aby pokazać przykład nieprawidłowego użycia wstępnego wczytywania, dodaj też wskazówkę dotyczącą wstępnego wczytywania tego zasobu.

<head>
  <!-- ... -->
  <link rel="preload" href="main.css" as="style">
  <link rel="preload" href="details.css" as="style">
</head>

Załaduj ponownie aplikację i sprawdź panel Sieć. Wysyłane jest żądanie pobrania elementu details.css, mimo że nie jest on używany przez stronę internetową.

Panel sieci z niepotrzebnym wstępnym wczytywaniem

Gdy wstępnie wczytany zasób nie jest używany przez stronę w ciągu kilku sekund od jej wczytania, Chrome wyświetla ostrzeżenie w panelu Konsola.

Ostrzeżenie o wstępnym wczytywaniu w konsoli

To ostrzeżenie może Ci pomóc w określeniu, czy masz jakieś wstępnie wczytane zasoby, które nie są od razu używane przez Twoją stronę internetową. Możesz teraz usunąć niepotrzebny link do wstępnego wczytywania tej strony.

<head>
  <!-- ... -->
  <link rel="preload" href="main.css" as="style">
  <link rel="preload" href="details.css" as="style">
</head>

Listę wszystkich typów zasobów, które można pobrać wraz z prawidłowymi wartościami, które należy zastosować w przypadku atrybutu as, znajdziesz w artykule MDN na temat wstępnego wczytywania.

Wstępne pobieranie przyszłych zasobów

Pobieranie wstępne to kolejna wskazówka dla przeglądarki, która może służyć do wysyłania żądań dotyczących zasobów używanych na innej ścieżce nawigacji, ale z niższym priorytetem niż inne ważne zasoby potrzebne na bieżącej stronie.

W tej witrynie kliknięcie obrazu powoduje przejście do osobnej details/ścieżki.

Szczegóły trasy

Oddzielny plik CSS, details.css, zawiera wszystkie style potrzebne na tej prostej stronie. Dodaj element linku do index.html, aby wstępnie pobrać ten zasób.

<head>
  <!-- ... -->
  <link rel="prefetch" href="details.css">
</head>

Aby dowiedzieć się, jak to wywołuje żądanie pliku, otwórz panel Sieć w Narzędziach deweloperskich i odznacz opcję Wyłącz pamięć podręczną.

Wyłączanie pamięci podręcznej w Narzędziach deweloperskich w Chrome

Odśwież aplikację i zwróć uwagę, jak po pobraniu wszystkich innych plików wysyłane jest żądanie o bardzo niskim priorytecie.details.css

Panel sieci z wstępnie pobranym zasobem

Otwórz Narzędzia deweloperskie i kliknij obraz w witrynie, aby przejść do strony details. Ponieważ element linku jest używany w details.html do pobierania details.css, żądanie zasobu jest wysyłane zgodnie z oczekiwaniami.

Żądania sieciowe na stronie z informacjami

Kliknij żądanie sieciowe details.css w Narzędziach deweloperskich, aby wyświetlić jego szczegóły. Zauważysz, że plik jest pobierany z pamięci podręcznej przeglądarki.

Szczegóły żądania pobrane z pamięci podręcznej na dysku

Prefetch wykorzystuje czas bezczynności przeglądarki, aby wcześniej wysłać żądanie zasobu potrzebnego na innej stronie. Przyspiesza to przyszłe żądania nawigacji, ponieważ przeglądarka może szybciej buforować zasoby i w razie potrzeby wyświetlać je z pamięci podręcznej.

Wstępne ładowanie i pobieranie z wyprzedzeniem za pomocą webpacka

W artykule Zmniejszanie rozmiaru pakietów JavaScript za pomocą dzielenia kodu omówiono używanie importów dynamicznych do dzielenia pakietu na kilka części. Pokazujemy to na przykładzie prostej aplikacji, która dynamicznie importuje moduł z biblioteki Lodash po przesłaniu formularza.

Aplikacja Magic Sorter, która demonstruje dzielenie kodu

Glitcha dla tej aplikacji znajdziesz tutaj.

Poniższy blok kodu, który znajduje się w src/index.js,, odpowiada za dynamiczne importowanie metody po kliknięciu przycisku.

form.addEventListener("submit", e => {
  e.preventDefault()
  import('lodash.sortby')
    .then(module => module.default)
    .then(sortInput())
    .catch(err => { alert(err) });
});

Podział pakietu poprawia czas wczytywania strony, ponieważ zmniejsza jej początkowy rozmiar. Wersja 4.6.0 webpacka obsługuje wstępne wczytywanie lub pobieranie fragmentów, które są importowane dynamicznie. Na przykładzie tej aplikacji metodę lodash można wstępnie pobrać w czasie bezczynności przeglądarki. Gdy użytkownik naciśnie przycisk, nie będzie opóźnienia w pobieraniu zasobu.

Użyj w dynamicznym imporcie konkretnego parametru komentarza webpackPrefetch, aby wstępnie pobrać określony fragment. Oto jak to wygląda w przypadku tej konkretnej aplikacji.

form.addEventListener("submit", e => {
  e.preventDefault()
  import(/* webpackPrefetch: true */ 'lodash.sortby')
    .then(module => module.default)
    .then(sortInput())
    .catch(err => { alert(err) });
});

Po ponownym załadowaniu aplikacji webpack wstrzykuje do sekcji head dokumentu tag pobierania z wyprzedzeniem dla zasobu. Możesz to sprawdzić w panelu Elementy w Narzędziach deweloperskich.

Panel Elementy z tagiem pobierania wstępnego

Obserwacja żądań w panelu Sieć pokazuje też, że ten fragment jest pobierany z niskim priorytetem po zażądaniu wszystkich innych zasobów.

Panel sieci z wstępnie pobranym żądaniem

W tym przypadku bardziej przydatne jest wstępne pobieranie, ale webpack obsługuje też wstępne wczytywanie fragmentów importowanych dynamicznie.

import(/* webpackPreload: true */ 'module')

Podsumowanie

Po ukończeniu tego laboratorium kodu będziesz mieć solidną wiedzę o tym, jak wstępne wczytywanie lub pobieranie określonych zasobów może poprawić wrażenia użytkowników Twojej witryny. Warto wspomnieć, że tych technik nie należy stosować w przypadku wszystkich zasobów, a nieprawidłowe użycie może pogorszyć wydajność. Najlepsze wyniki można uzyskać tylko wtedy, gdy wstępne wczytywanie lub pobieranie z wyprzedzeniem jest stosowane selektywnie.

Podsumowując:

  • Używaj wstępnego wczytywania w przypadku zasobów, które są wykrywane późno, ale mają kluczowe znaczenie dla bieżącej strony.
  • Używaj pobierania z wyprzedzeniem w przypadku zasobów potrzebnych w przyszłości w ramach trasy nawigacji lub działania użytkownika.

Nie wszystkie przeglądarki obsługują obecnie zarówno wstępne wczytywanie, jak i wstępne pobieranie. Oznacza to, że nie wszyscy użytkownicy Twojej aplikacji mogą zauważyć poprawę wydajności.

Jeśli chcesz dowiedzieć się więcej o tym, jak wstępne wczytywanie i wstępne pobieranie mogą wpływać na Twoją stronę internetową, przeczytaj te artykuły: