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

Dzięki temu ćwiczeniu w programowaniu wydajność poniższej strony internetowej poprawi się przez wstępne wczytywanie i pobieranie kilku zasobów:

Zrzut ekranu aplikacji

Zmierz odległość

Zanim wprowadzisz jakiekolwiek optymalizacje, zmierz najpierw skuteczność witryny.

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

Przeprowadź kontrolę wydajności Lighthouse (Lighthouse > Opcje > Wydajność) w wersji Glitch na żywo (zobacz też Znajdź możliwości poprawy wydajności za pomocą Lighthouse).

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

Lighthouse: audyt wstępnego wczytywania żądań kluczy
  • Aby otworzyć Narzędzia dla programistów, naciśnij `Control+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 przez oddzielny plik JavaScript (fetch-css.js), który po zdarzeniu window.onLoad dołącza element Link do DOM. 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 elementach main.css jest pobierana dopiero po zakończeniu pobierania pliku CSS.

Łańcuch krytycznych żądań określa kolejność zasobów, które są traktowane priorytetowo i pobierane przez przeglądarkę. W przypadku tej strony internetowej wygląda to tak:

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

Plik CSS znajduje się na trzecim poziomie łańcucha żądań, więc Lighthouse zidentyfikował go jako zasób odkryty późno.

Wstępne wczytywanie ważnych zasobów

Plik main.css to kluczowy zasób, który jest potrzebny natychmiast po załadowaniu 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 wczytania linku, aby poinformować przeglądarkę o potrzebie wcześniejszego pobrania pliku. W tym celu dodaj element Link do nagłówka dokumentu.

Dodaj tag wstępnego wczytania dla tej aplikacji:

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

Atrybut as służy do identyfikowania typu zasobu, który jest pobierany, a atrybut as="style" służy do wstępnego wczytania plików arkuszy stylów.

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

Panel sieci z zasobem wstępnie załadowanym

Zwróć uwagę, że przeglądarka pobiera plik CSS, zanim skończy się analizowanie kodu JavaScript odpowiedzialnego za jego pobieranie. W przypadku wczytania wstępnego przeglądarka wie, że musi pobrać zasób z wyprzedzeniem, ponieważ jest on kluczowy dla strony internetowej.

Nieprawidłowe użycie funkcji wstępnego ładowania może obniżyć wydajność, ponieważ powoduje niepotrzebne żądania dotyczące nieużywanych zasobów. W tej aplikacji details.css to inny 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 funkcji wstępnego wczytania, dodaj do tego zasobu również podpowiedź dotyczącą wstępnego wczytania.

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

Załaduj ponownie aplikację i przyjrzyj się panelowi Network (Sieć). Wysyłane jest żądanie pobrania elementu details.css, mimo że strona internetowa go nie używa.

Panel sieci z niepotrzebnym wstępnym wczytaniem

Jeśli w ciągu kilku sekund po załadowaniu zasobów wstępnie załadowanych strona nie użyje ich, Chrome wyświetli ostrzeżenie w panelu Konsola.

Ostrzeżenie o wstępnym wczytaniu w konsoli

Użyj tego ostrzeżenia, aby sprawdzić, czy masz jakieś załadowane wstępnie zasoby, których Twoja strona internetowa nie używa od razu. Możesz teraz usunąć z tej strony niepotrzebny link do wstępnego wczytania.

<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 poprawnymi wartościami, których należy użyć w atrybucie as, znajdziesz w artykule w MDN na temat wstępnego wczytywania.

Pobieranie w poprzednim czasie przyszłych zasobów

Pobieranie z wyprzedzeniem to kolejna wskazówka do przeglądarki, której można użyć, aby wysłać żądanie zasobu użytego na potrzeby innej trasy nawigacji, ale z niższym priorytetem niż inne ważne zasoby wymagane w przypadku bieżącej strony.

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

Trasa szczegółów

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

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

Aby dowiedzieć się, jak wyzwala to żą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

Ponownie załaduj aplikację i zwróć uwagę, że po pobraniu wszystkich innych plików wysyłane jest żądanie dotyczące pliku details.css o bardzo niskim priorytecie.

Panel sieci z wstępnie pobranym zasobem

Gdy otwarte są Narzędzia deweloperskie, kliknij obraz w witrynie, aby przejść na stronę details. Ponieważ w elementie linka details.html używanym do pobierania zasobu details.css występuje element linka, żądanie dotyczące tego zasobu jest wysyłane zgodnie z oczekiwaniami.

Żądania sieci na stronie z informacjami

Kliknij żądanie sieciowe details.css w Narzędziach deweloperskich, aby wyświetlić jego szczegóły. Plik zostanie pobrany z pamięci podręcznej przeglądarki.

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

Wykorzystując czas bezczynności przeglądarki, funkcja wstępnego pobierania wysyła wcześniej żądanie zasobu potrzebnego na innej stronie. Przyspiesza to przyszłe żądania nawigacji, ponieważ pozwala przeglądarce wcześniej wczytać zasób do pamięci podręcznej i w razie potrzeby wyświetlać go z pamięci podręcznej.

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

W poście Zmniejsz rozmiary ładunków JavaScript dzięki dzieleniu kodu omawiamy używanie importów dynamicznych do dzielenia pakietu na kilka fragmentów. Można to sprawdzić w prostej aplikacji, która dynamicznie importuje moduł z Lodash podczas przesyłania formularza.

Aplikacja Magic Sorter prezentująca podział kodu

Tutaj możesz uzyskać dostęp do Glitcha dla tej aplikacji.

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

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 jego początkowy rozmiar. Wersja 4.6.0 pakietu webpack obsługuje wstępny wczytywanie lub wyprzedzające wczytywanie fragmentów, które są importowane dynamicznie. Używając tej aplikacji jako przykładu, metoda lodash może być wstępnie pobrana w czasie bezczynności przeglądarki. Gdy użytkownik naciśnie przycisk, nie wystąpi opóźnienie w pobraniu zasobu.

Aby pobrać w ramach importu dynamicznego konkretny fragment, użyj parametru komentarza webpackPrefetch. 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 tag pobierania z wyprzedzeniem dla zasobu do nagłówka dokumentu. Można to zobaczyć w panelu Elementy w Narzędziach deweloperskich.

Panel elementów z tagiem pobierania wstępnego

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

Panel sieci z żądaniem pobierania w poprzednim etapie

Chociaż w tym przypadku bardziej przydatne jest wstępne pobieranie, webpack obsługuje też wstępne pobieranie fragmentów, które są importowane dynamicznie.

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

Podsumowanie

Dzięki tym ćwiczeniom w Codelabs dowiesz się, jak wstępne ładowanie lub pobieranie określonych zasobów może poprawić wrażenia użytkowników Twojej witryny. Należy pamiętać, że tych technik nie należy stosować w przypadku każdego zasobu, a nieprawidłowe ich użycie może pogorszyć wydajność. Najlepsze wyniki uzyskuje się, stosując tylko wczytywanie wstępne lub wczytywanie wstępne selektywnie.

Podsumowując:

  • Użyj wstępnego wczytania w przypadku zasobów, które są wykrywane późno, ale są kluczowe dla bieżącej strony.
  • Użyj wstępnego wczytania w przypadku zasobów potrzebnych do przyszłego planowania trasy lub działania użytkownika.

Nie wszystkie przeglądarki obsługują zarówno wstępny, jak i wcześniejszy wstępny wczytywanie. Oznacza to, że nie wszyscy użytkownicy Twojej aplikacji zauważą poprawę jej wydajności.

Jeśli chcesz dowiedzieć się więcej o szczegółowych aspektach wpływu wstępnego wczytywania i wstępnego pobierania na stronę internetową, przeczytaj te artykuły: