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

W ramach tego ćwiczenia w Codelabs wydajność następującej strony internetowej poprawi się przez wstępne wczytywanie i pobieranie kilku zasobów:

Zrzut ekranu aplikacji

Zmierz odległość

Zanim dodasz jakiekolwiek optymalizacje, sprawdź skuteczność witryny.

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

Przeprowadź audyt wydajności Lighthouse (Lighthouse > Opcje > Wydajność) w aktualnej wersji Glitcha (zobacz też Odkrywanie możliwości zwiększenia skuteczności dzięki Lighthouse).

Lighthouse pokazuje tę nieudaną kontrolę zasobu, który został pobrany później:

Lighthouse: kontrola wstępnego wczytywania kluczy
  • Naciśnij „Control + Shift + J” (lub „Command + Option + J” na Macu), aby otworzyć Narzędzia deweloperskie.
  • Kliknij kartę Sieć.
Panel sieci z późno wykrytym zasobem

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

Łańcuch żądań krytycznych reprezentuje kolejność zasobów, które mają priorytet i są pobierane przez przeglądarkę. Obecnie wygląda ona tak:

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

Plik CSS znajduje się na 3 poziomie łańcucha żądań, więc narzędzie Lighthouse rozpoznało go jako zasób, który został wykryty późno.

Wstępnie wczytuj najważniejsze zasoby

Plik main.css to kluczowy zasób potrzebny od razu po wczytaniu strony. W przypadku ważnych plików, takich jak ten zasób, które są pobierane późno w aplikacji, użyj tagu wstępnego wczytywania linku, aby poinformować przeglądarkę, że powinna pobrać je wcześniej. W tym celu dodaj element Link do nagłówka dokumentu.

Dodaj tag wstępnego wczytywania dla tej aplikacji:

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

Atrybut as określa, jaki typ zasobu jest pobierany, a as="style" służy do wstępnego wczytywania plików arkuszy stylów.

Załaduj ponownie aplikację i spójrz na panel Network (Sieć) w Narzędziach deweloperskich.

Panel sieci ze wstępnie wczytanym zasobem

Zwróć uwagę, że przeglądarka pobiera plik CSS, zanim jeszcze zakończy się analiza kodu JavaScript odpowiedzialnego za jego pobieranie. Dzięki wstępnemu wczytywaniu zasób może skorzystać z wyprzedzenieowego pobierania zasobu przy założeniu, że jest on krytyczny dla strony internetowej.

Nieprawidłowo używane wstępne wczytywanie może obniżyć wydajność, ponieważ będzie wysyłać niepotrzebne żądania dotyczące 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 na potrzeby osobnego pliku /details route. Aby pokazać przykład nieprawidłowego użycia wstępnego wczytywania, dodaj też wskazówkę dotyczącą wstępnego wczytywania także dla 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 spójrz na 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ępnie ładowaniem

Jeśli wstępnie wczytany zasób nie zostanie wykorzystany przez stronę w ciągu kilku sekund po załadowaniu strony, Chrome wyświetla ostrzeżenie w panelu Konsola.

Ostrzeżenie dotyczące wstępnego wczytywania w konsoli

To ostrzeżenie pokazuje, czy masz jakieś wstępnie wczytane zasoby, które nie są używane od razu przez Twoją stronę internetową. Teraz możesz usunąć niepotrzebny link 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ć, oraz prawidłowych wartości, których należy użyć w przypadku atrybutu as, znajdziesz w artykule w MDN na temat wstępnego wczytywania.

Pobieraj z wyprzedzeniem przyszłe zasoby

Pobieranie z wyprzedzeniem to kolejna wskazówka dotycząca przeglądarki, która pozwala wysyłać żądania zasobów używanych na potrzeby innej trasy nawigacji, ale o niższym priorytecie niż inne ważne zasoby potrzebne w przypadku bieżącej strony.

Kliknięcie obrazu na tej stronie spowoduje przejście do osobnej trasy details/.

Szczegóły trasy

Oddzielny plik CSS (details.css) zawiera wszystkie style potrzebne w przypadku tej prostej strony. Dodaj element link do tabeli index.html, aby pobrać ten zasób z wyprzedzeniem.

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

Aby dowiedzieć się, jak powoduje to wysłanie żądania 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

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

Panel sieci z wstępnie pobranym zasobem

Po otwarciu Narzędzi deweloperskich kliknij obraz w witrynie, aby przejść na stronę details. Element link jest używany w funkcji details.html do pobierania elementu details.css, dlatego jest wysyłane żądanie dotyczące zasobu zgodnie z oczekiwaniami.

Żądania sieciowe na stronie szczegółów

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

Żądanie szczegółów zostało pobrane z pamięci podręcznej dysku

Dzięki wykorzystaniu czasu bezczynności przeglądarki pobieranie z wyprzedzeniem wysyła wczesne żądanie o zasób potrzebny dla innej strony. Przyspiesza to przyszłe żądania nawigacji, umożliwiając przeglądarce szybsze zapisywanie zasobu w pamięci podręcznej i wyświetlanie go z pamięci podręcznej w razie potrzeby.

Wstępne ładowanie i wstępne wczytywanie za pomocą pakietu Webpack

W poście Ogranicz ładunki JavaScript dzięki podziałowi kodu omawiamy wykorzystanie importu dynamicznego do podziału pakietu na wiele fragmentów. Widać to w prostej aplikacji, która dynamicznie importuje moduł z usługi Lodash przy przesyłaniu formularza.

Aplikacja Magic Sorter pokazująca podział kodu

Informacje o problemach z błędami w tej aplikacji znajdziesz tutaj.

Ten blok kodu, który znajduje się w elemencie 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 skraca czas wczytywania strony dzięki zmniejszeniu jego początkowego rozmiaru. Wersja 4.6.0 pakietu webowego zapewnia obsługę wstępnego wczytywania i wstępnego pobierania fragmentów, które są importowane dynamicznie. Na przykład w tej aplikacji metoda lodash może być pobierana z wyprzedzeniem w czasie bezczynności przeglądarki; gdy użytkownik naciśnie przycisk, pobranie zasobu nie występuje.

Użyj konkretnego parametru komentarza webpackPrefetch w dynamicznym imporcie, aby pobrać z wyprzedzeniem konkretny fragment. Tak będzie 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 w nagłówku dokumentu tag pobierania z wyprzedzeniem dla danego zasobu. Możesz to zobaczyć w panelu Elementy w Narzędziach deweloperskich.

Panel elementów z tagiem pobierania z wyprzedzeniem

Obserwowanie żądań w panelu Sieć pokazuje też, że ten fragment jest pobierany z niskim priorytetem po wysłaniu żądania wszystkich innych zasobów.

Panel sieci z wstępnie pobranym żądaniem

W tym przypadku pobieranie z wyprzedzeniem ma większą sens, ale pakiet internetowy zapewnia również obsługę wstępnego wczytywania fragmentów, które są dynamicznie importowane.

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

Podsumowanie

Dzięki tym ćwiczeniom z programowania dowiesz się, jak wstępne ładowanie i pobieranie określonych zasobów może poprawić wrażenia użytkowników Twojej witryny. Pamiętaj, że nie należy stosować tych technik w przypadku niektórych zasobów, a ich nieprawidłowe korzystanie może mieć negatywny wpływ na wydajność. Najlepsze wyniki uzyskuje się tylko przy wstępnym wczytywaniu lub pobieraniu z wyprzedzeniem tylko w przypadku selektywnego wczytywania.

Podsumujmy:

  • W przypadku zasobów wykrytych z opóźnieniem, które mają kluczowe znaczenie dla bieżącej strony, używaj funkcji wstępnego ładowania.
  • Używaj funkcji pobierania z wyprzedzeniem w przypadku zasobów, które są potrzebne na potrzeby przyszłej trasy nawigacji lub działania użytkownika.

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

Więcej informacji o konkretnych aspektach wpływu wstępnego wczytywania i pobierania stron znajdziesz w tych artykułach: