Nie walcz ze skanerem wstępnego wczytywania przeglądarki

Dowiedz się, czym jest skaner wstępnego wczytywania przeglądarki, jak pomaga zwiększyć wydajność i jak nie przeszkadzać mu w działaniu.

Jednym z często pomijanych aspektów optymalizacji Page Speed jest znajomość działania przeglądarki. Przeglądarki wprowadzają pewne optymalizacje, aby poprawić wydajność w sposób, którego my jako deweloperzy nie możemy zastosować – ale tylko wtedy, gdy te optymalizacje nie zostaną przypadkowo zakłócone.

Jedną z wewnętrznych optymalizacji przeglądarki, którą warto poznać, jest skaner wstępnego wczytywania. W tym poście wyjaśnimy, jak działa skaner wstępnego wczytywania, a co ważniejsze, jak nie przeszkadzać mu w pracy.

Czym jest skaner wstępnego wczytywania?

Każda przeglądarka ma główny parser HTML, który tokenizuje nieprzetworzone znaczniki i przetwarza je na model obiektowy. Wszystko to dzieje się do momentu, gdy parser zatrzyma się po znalezieniu zasobu blokującego, takiego jak arkusz stylów wczytany za pomocą elementu <link> lub skrypt wczytany za pomocą elementu <script> bez atrybutu async lub defer.

Diagram parsera HTML.
Rys. 1. Schemat pokazujący, jak można zablokować główny parser HTML przeglądarki. W tym przypadku parser napotyka element <link> zewnętrznego pliku CSS, który uniemożliwia przeglądarce przeanalizowanie pozostałej części dokumentu, a nawet wyrenderowanie jakiejkolwiek jego części, dopóki plik CSS nie zostanie pobrany i przeanalizowany.

W przypadku plików CSS renderowanie jest blokowane, aby zapobiec mignięciu nieostylowanej treści (FOUC), czyli sytuacji, w której nieostylowana wersja strony jest widoczna przez chwilę, zanim zostaną do niej zastosowane style.

Strona główna web.dev bez stylów (po lewej) i ze stylami (po prawej).
Rys. 2. Symulowany przykład FOUC. Po lewej stronie znajduje się strona główna web.dev bez stylów. Po prawej stronie znajduje się ta sama strona z zastosowanymi stylami. Stan bez stylu może wystąpić w ciągu sekundy, jeśli przeglądarka nie blokuje renderowania podczas pobierania i przetwarzania arkusza stylów.

Przeglądarka blokuje też analizowanie i renderowanie strony, gdy napotka elementy <script> bez atrybutu defer lub async.

Dzieje się tak, ponieważ przeglądarka nie może mieć pewności, czy dany skrypt nie zmodyfikuje modelu DOM, gdy główny parser HTML będzie jeszcze wykonywał swoje zadanie. Dlatego powszechną praktyką jest wczytywanie kodu JavaScript na końcu dokumentu, aby skutki zablokowanego analizowania i renderowania były marginalne.

Są to dobre powody, dla których przeglądarka powinna blokować zarówno analizowanie, jak i renderowanie. Blokowanie tych ważnych kroków jest jednak niepożądane, ponieważ może opóźnić wykrywanie innych ważnych zasobów. Na szczęście przeglądarki starają się rozwiązać te problemy za pomocą dodatkowego parsera HTML, który nazywa się skanerem wstępnego wczytywania.

Diagram przedstawiający główny parser HTML (po lewej) i skaner wstępnego wczytywania (po prawej), który jest dodatkowym parserem HTML.
Rys. 3. Diagram przedstawiający, jak skaner wstępnego wczytywania działa równolegle z głównym parserem HTML, aby spekulatywnie wczytywać zasoby. W tym przypadku główny parser HTML jest blokowany, ponieważ wczytuje i przetwarza kod CSS, zanim będzie mógł zacząć przetwarzać znaczniki obrazu w elemencie <body>. Skaner wstępnego wczytywania może jednak zajrzeć do nieprzetworzonych znaczników, aby znaleźć ten zasób obrazu i rozpocząć jego wczytywanie, zanim główny parser HTML zostanie odblokowany.

Skaner wstępnego wczytywania działa spekulacyjnie, co oznacza, że analizuje nieprzetworzone znaczniki, aby znaleźć zasoby do pobrania, zanim zostaną one wykryte przez główny parser HTML.

Jak sprawdzić, czy skaner wstępnego wczytywania działa

Skaner wstępnego wczytywania istnieje z powodu zablokowanego renderowania i analizowania. Gdyby te 2 problemy z wydajnością nie występowały, skaner wstępnego wczytywania nie byłby zbyt przydatny. To, czy strona internetowa korzysta ze skanera wstępnego wczytywania, zależy od tych zjawisk blokowania. Aby to zrobić, możesz wprowadzić sztuczne opóźnienie żądań, aby dowiedzieć się, gdzie działa skaner wstępnego wczytywania.

Weźmy na przykład tę stronę z podstawowym tekstem i obrazami oraz arkuszem stylów. Pliki CSS blokują zarówno renderowanie, jak i analizowanie, dlatego wprowadzasz sztuczne opóźnienie o 2 sekundy dla arkusza stylów za pomocą usługi pośredniczącej. To opóźnienie ułatwia sprawdzenie w wodospadzie sieci, gdzie działa skaner wstępnego wczytywania.

Wykres kaskadowy sieci WebPageTest przedstawia sztuczne opóźnienie o 2 sekundy nałożone na arkusz stylów.
Rys. 4. Wykres kaskadowy sieci WebPageTest dla strony internetowej uruchomionej w Chrome na urządzeniu mobilnym przez symulowane połączenie 3G. Chociaż arkusz stylów jest sztucznie opóźniony przez serwer proxy o 2 sekundy, zanim zacznie się wczytywać, obraz znajdujący się później w kodzie znaczników jest wykrywany przez skaner wstępnego wczytywania.

Jak widać na wykresie kaskadowym, skaner wstępnego wczytywania wykrywa element <img>, nawet gdy renderowanie i analizowanie dokumentu są zablokowane. Bez tej optymalizacji przeglądarka nie może pobierać zasobów w okresie blokowania, a więcej żądań zasobów będzie wysyłanych kolejno, a nie jednocześnie.

Po omówieniu tego prostego przykładu przyjrzyjmy się kilku rzeczywistym wzorcom, w których skaner wstępnego wczytywania może zostać pokonany, oraz temu, co można zrobić, aby je naprawić.

Wstrzyknięto skrypty async

Załóżmy, że w elemencie <head> masz kod HTML, który zawiera taki wbudowany kod JavaScript:

<script>
  const scriptEl = document.createElement('script');
  scriptEl.src = '/yall.min.js';

  document.head.appendChild(scriptEl);
</script>

Wstrzykiwane skrypty są domyślnie async, więc po wstrzyknięciu ten skrypt będzie zachowywał się tak, jakby zastosowano do niego atrybut async. Oznacza to, że zostanie on uruchomiony tak szybko, jak to możliwe, i nie będzie blokować renderowania. Brzmi optymalnie, prawda? Jeśli jednak założysz, że ten wbudowany element <script> występuje po elemencie <link>, który wczytuje zewnętrzny plik CSS, uzyskasz nieoptymalny wynik:

Ten wykres WebPageTest pokazuje, że skanowanie wstępne zostało pominięte po wstrzyknięciu skryptu.
Rys. 5. Wykres kaskadowy sieci WebPageTest strony internetowej uruchomionej w Chrome na urządzeniu mobilnym przez symulowane połączenie 3G. Strona zawiera 1 arkusz stylów i wstrzyknięty skrypt async. Skaner wstępnego wczytywania nie może wykryć skryptu podczas fazy blokowania renderowania, ponieważ jest on wstrzykiwany po stronie klienta.

Przeanalizujmy, co się stało:

  1. W sekundzie 0 wysyłane jest żądanie głównego dokumentu.
  2. W 1, 4 sekundzie dociera pierwszy bajt żądania nawigacji.
  3. W 2, 0 sekundzie następuje żądanie CSS i obrazu.
  4. Ponieważ parser jest blokowany podczas wczytywania arkusza stylów, a wbudowany kod JavaScript, który wstrzykuje skrypt async, pojawia się po tym arkuszu stylów w 2,6 sekundy, funkcje, które zapewnia ten skrypt, nie są dostępne tak szybko, jak mogłyby być.

Jest to nieoptymalne, ponieważ żądanie skryptu następuje dopiero po zakończeniu pobierania arkusza stylów. Spowoduje to opóźnienie uruchomienia skryptu. Z kolei element <img> jest wykrywalny w znacznikach dostarczanych przez serwer, więc skaner wstępnego wczytywania go wykrywa.

Co się stanie, jeśli użyjesz zwykłego tagu <script> z atrybutem async, zamiast wstrzykiwać skrypt do modelu DOM?

<script src="/yall.min.js" async></script>

Oto wynik:

Wodospad sieciowy WebPageTest pokazujący, jak skrypt asynchroniczny wczytany za pomocą elementu skryptu HTML jest nadal wykrywalny przez skaner wstępnego wczytywania przeglądarki, mimo że główny parser HTML przeglądarki jest blokowany podczas pobierania i przetwarzania arkusza stylów.
Rys. 6. Wykres kaskadowy sieci WebPageTest strony internetowej uruchomionej w Chrome na urządzeniu mobilnym z symulowanym połączeniem 3G. Strona zawiera jeden arkusz stylów i jeden element async <script>. Skaner wstępnego wczytywania wykrywa skrypt podczas fazy blokowania renderowania i wczytuje go jednocześnie z arkuszem CSS.

Może pojawić się pokusa, aby zasugerować, że te problemy można rozwiązać za pomocą rel=preload. To rozwiązanie na pewno by zadziałało, ale mogłoby mieć pewne skutki uboczne. Po co używać rel=preload do rozwiązywania problemu, którego można uniknąć, nie wstrzykując elementu <script> do DOM?

Wodospad WebPageTest pokazujący, jak wskazówka dotycząca zasobów rel=preload jest używana do promowania wykrywania asynchronicznie wstrzykniętego skryptu, choć w sposób, który może mieć niezamierzone skutki uboczne.
Rys. 7. Wykres kaskadowy sieci WebPageTest strony internetowej uruchomionej w Chrome na urządzeniu mobilnym przez symulowane połączenie 3G. Strona zawiera jeden arkusz stylów i wstrzyknięty skrypt async, ale skrypt async jest wstępnie wczytywany, aby został wcześniej wykryty.

Wstępne wczytywanie „rozwiązuje” ten problem, ale wprowadza nowy: skrypt async w pierwszych 2 wersjach demonstracyjnych – mimo że jest wczytywany w <head> – jest wczytywany z priorytetem „Niski”, podczas gdy arkusz stylów jest wczytywany z priorytetem „Najwyższy”. W ostatniej wersji demonstracyjnej, w której skrypt async jest wstępnie wczytywany, arkusz stylów jest nadal wczytywany z priorytetem „Najwyższy”, ale priorytet skryptu został podniesiony do „Wysoki”.

Gdy priorytet zasobu zostanie podniesiony, przeglądarka przydzieli mu większą przepustowość. Oznacza to, że mimo iż arkusz stylów ma najwyższy priorytet, podwyższony priorytet skryptu może powodować rywalizację o przepustowość. Może to być istotne w przypadku wolnych połączeń lub gdy zasoby są dość duże.

Odpowiedź jest prosta: jeśli skrypt jest potrzebny podczas uruchamiania, nie omijaj skanera wstępnego wczytywania, wstrzykując go do DOM. Eksperymentuj z umieszczaniem elementu <script> oraz z atrybutami takimi jak defer i async.

Leniwe ładowanie za pomocą JavaScriptu

Leniwe ładowanie to świetna metoda oszczędzania danych, która jest często stosowana w przypadku obrazów. Czasami jednak leniwe ładowanie jest nieprawidłowo stosowane do obrazów, które znajdują się „nad częścią strony widoczną na ekranie”.

Może to powodować problemy z wykrywaniem zasobów przez skaner wstępnego wczytywania i niepotrzebnie opóźniać wykrywanie odniesienia do obrazu, pobieranie go, dekodowanie i wyświetlanie. Weźmy na przykład te znaczniki obrazu:

<img data-src="/sand-wasp.jpg" alt="Sand Wasp" width="384" height="255">

Użycie prefiksu data- jest powszechnym wzorcem w przypadku leniwego ładowania opartego na JavaScript. Gdy obraz zostanie przewinięty do widocznego obszaru, moduł leniwego ładowania usuwa prefiks data-, co oznacza, że w poprzednim przykładzie data-src staje się src. Ta aktualizacja powoduje, że przeglądarka pobiera zasób.

Ten wzorzec nie jest problematyczny, dopóki nie zostanie zastosowany do obrazów, które znajdują się w widocznym obszarze podczas uruchamiania. Skaner wstępnego wczytywania nie odczytuje atrybutu data-src w taki sam sposób jak atrybutu src (lub srcset), więc odwołanie do obrazu nie jest wykrywane wcześniej. Co gorsza, obraz jest wczytywany dopiero po pobraniu, skompilowaniu i wykonaniu kodu JavaScript leniwego ładowania.

Wykres kaskadowy sieci WebPageTest pokazujący, jak leniwie ładowany obraz, który znajduje się w widocznym obszarze podczas uruchamiania, jest opóźniony, ponieważ skaner wstępnego wczytywania przeglądarki nie może znaleźć zasobu obrazu i ładuje się tylko wtedy, gdy załaduje się kod JavaScript wymagany do leniwego ładowania. Obraz jest wykrywany znacznie później, niż powinien.
Rys. 8. Wykres kaskadowy sieci WebPageTest strony internetowej uruchomionej w Chrome na urządzeniu mobilnym przez symulowane połączenie 3G. Zasób obrazu jest niepotrzebnie ładowany leniwie, mimo że jest widoczny w widocznym obszarze podczas uruchamiania. Uniemożliwia to działanie skanera wstępnego wczytywania i powoduje niepotrzebne opóźnienie.

W zależności od rozmiaru obrazu, który może zależeć od rozmiaru widocznego obszaru, może on być elementem kandydującym do największego wyrenderowania treści (LCP). Gdy skaner wstępnego wczytywania nie może pobrać zasobu obrazu z wyprzedzeniem(np. gdy arkusze stylów strony blokują renderowanie), LCP ulega pogorszeniu.

Rozwiązaniem jest zmiana znaczników obrazu:

<img src="/sand-wasp.jpg" alt="Sand Wasp" width="384" height="255">

To optymalny wzorzec dla obrazów, które znajdują się w widocznym obszarze podczas uruchamiania, ponieważ skaner wstępnego wczytywania szybciej wykryje i pobierze zasób obrazu.

Wykres kaskadowy sieci WebPageTest przedstawiający scenariusz wczytywania obrazu w widocznym obszarze podczas uruchamiania. Obraz nie jest ładowany leniwie, co oznacza, że nie jest zależny od skryptu, więc skaner wstępnego wczytywania może go wykryć wcześniej.
Rys. 9. Wykres kaskadowy sieci WebPageTest strony internetowej uruchomionej w Chrome na urządzeniu mobilnym przez symulowane połączenie 3G. Skaner wstępnego wczytywania wykrywa zasób obrazu, zanim zacznie się wczytywanie kodu CSS i JavaScriptu, co daje przeglądarce przewagę przy jego wczytywaniu.

W tym uproszczonym przykładzie wynik to poprawa wskaźnika LCP o 100 milisekund przy wolnym połączeniu. Może się wydawać, że to niewielka poprawa, ale jeśli weźmiesz pod uwagę, że rozwiązanie polega na szybkiej poprawce znaczników i że większość stron internetowych jest bardziej złożona niż ten zestaw przykładów, to jest to duża zmiana. Oznacza to, że kandydaci na LCP mogą konkurować o przepustowość z wieloma innymi zasobami, dlatego optymalizacje takie jak ta stają się coraz ważniejsze.

obrazy tła CSS,

Pamiętaj, że skaner wstępnego wczytywania przeglądarki skanuje znaczniki. Nie skanuje innych typów zasobów, takich jak CSS, które mogą obejmować pobieranie obrazów, do których odwołuje się właściwość background-image.

Podobnie jak w przypadku HTML przeglądarki przetwarzają CSS na własny model obiektowy, znany jako CSSOM. Jeśli podczas tworzenia CSSOM zostaną wykryte zasoby zewnętrzne, żądania dotyczące tych zasobów są wysyłane w momencie ich wykrycia, a nie przez skaner wstępnego wczytywania.

Załóżmy, że kandydatem do LCP na Twojej stronie jest element z właściwością CSS background-image. Podczas wczytywania zasobów:

Wykres kaskadowy sieci WebPageTest przedstawiający stronę z kandydatem do LCP wczytanym z CSS za pomocą właściwości background-image. Obraz kandydujący do LCP jest w typie zasobu, którego skaner wstępnego wczytywania przeglądarki nie może sprawdzić, więc wczytywanie zasobu jest opóźnione do czasu pobrania i przetworzenia kodu CSS, co opóźnia czas renderowania kandydata do LCP.
Rys. 10. Wykres kaskadowy sieci WebPageTest strony internetowej uruchomionej w Chrome na urządzeniu mobilnym z symulowanym połączeniem 3G. Kandydatem do LCP na stronie jest element z właściwością CSS background-image (wiersz 3). Pobieranie żądanego obrazu rozpoczyna się dopiero wtedy, gdy parser CSS go znajdzie.

W takim przypadku skaner wstępnego wczytywania nie jest tak bardzo nieskuteczny, jak niezaangażowany. Jeśli jednak kandydat na LCP na stronie pochodzi z właściwości CSS background-image, warto wstępnie załadować ten obraz:

<!-- Make sure this is in the <head> below any
     stylesheets, so as not to block them from loading -->
<link rel="preload" as="image" href="lcp-image.jpg">

Ta wskazówka rel=preload jest niewielka, ale pomaga przeglądarce szybciej odkryć obraz:

Wykres kaskadowy sieci WebPageTest pokazujący, że obraz tła CSS (który jest kandydatem do LCP) wczytuje się znacznie szybciej dzięki użyciu wskazówki rel=preload. Czas LCP poprawia się o około 250 milisekund.
Rys. 11. Wykres kaskadowy sieci WebPageTest strony internetowej uruchomionej w Chrome na urządzeniu mobilnym z symulowanym połączeniem 3G. Kandydatem do LCP na stronie jest element z właściwością CSS background-image (wiersz 3). Wskazówka rel=preload pomaga przeglądarce wykryć obraz o około 250 milisekund szybciej niż bez wskazówki.

Dzięki wskazówce rel=preload kandydat LCP jest wykrywany wcześniej, co skraca czas LCP. Ta wskazówka pomaga rozwiązać problem, ale lepszym rozwiązaniem może być ocena, czy obraz kandydujący do LCP musi być wczytywany z CSS. Tag <img> daje większą kontrolę nad wczytywaniem obrazu odpowiedniego dla widocznego obszaru, a jednocześnie umożliwia skanerowi wstępnego wczytywania jego wykrycie.

Wstawianie zbyt wielu zasobów w kodzie

Wstawianie w kodzie to praktyka polegająca na umieszczaniu zasobu w kodzie HTML. Arkusze stylów możesz umieszczać w elementach <style>, skrypty w elementach <script>, a praktycznie każdy inny zasób – za pomocą kodowania base64.

Wstawianie zasobów może być szybsze niż ich pobieranie, ponieważ nie jest wysyłane osobne żądanie dotyczące zasobu. Jest on dostępny bezpośrednio w dokumencie i wczytuje się natychmiast. Ma jednak istotne wady:

  • Jeśli nie buforujesz kodu HTML (a nie możesz tego zrobić, jeśli odpowiedź HTML jest dynamiczna), zasoby wbudowane nigdy nie są buforowane. Wpływa to na wydajność, ponieważ zasobów wbudowanych nie można używać ponownie.
  • Nawet jeśli możesz zapisać kod HTML w pamięci podręcznej, zasoby wbudowane nie są udostępniane między dokumentami. Zmniejsza to wydajność buforowania w porównaniu z plikami zewnętrznymi, które można buforować i ponownie wykorzystywać w całym źródle.
  • Jeśli umieścisz zbyt wiele elementów w kodzie, opóźnisz wykrywanie zasobów przez skaner wstępnego wczytywania w dalszej części dokumentu, ponieważ pobieranie dodatkowych treści umieszczonych w kodzie zajmie więcej czasu.

Weźmy na przykład tę stronę. W pewnych warunkach kandydatem do LCP jest obraz u góry strony, a kod CSS znajduje się w osobnym pliku wczytywanym przez element <link>. Strona używa też 4 czcionek internetowych, które są żądane jako osobne pliki z zasobu CSS.

Wykres kaskadowy sieci WebPageTest strony z zewnętrznym plikiem CSS, który zawiera odwołania do 4 czcionek. Obraz kandydujący do LCP jest wykrywany przez skaner wstępnego wczytywania we właściwym czasie.
Rys. 12. Wykres kaskadowy sieci WebPageTest strony internetowej uruchomionej w Chrome na urządzeniu mobilnym przez symulowane połączenie 3G. Kandydatem na LCP strony jest obraz wczytany z elementu <img>, ale został on wykryty przez skaner wstępnego wczytywania, ponieważ arkusze CSS i czcionki wymagane do wczytania strony są wczytywane w osobnych zasobach, co nie opóźnia działania skanera wstępnego wczytywania.

Co się stanie, jeśli CSS i wszystkie czcionki zostaną wbudowane jako zasoby base64?

Wykres kaskadowy sieci WebPageTest strony z zewnętrznym plikiem CSS, który zawiera odwołania do 4 czcionek. Skaner wstępnego wczytywania wykrywa obraz LCP ze znacznym opóźnieniem .
Rys. 13. Wykres kaskadowy sieci WebPageTest strony internetowej uruchomionej w Chrome na urządzeniu mobilnym z symulowanym połączeniem 3G. Kandydatem do LCP strony jest obraz wczytany z elementu <img>, ale umieszczenie kodu CSS i jego 4 zasobów czcionek w elemencie `` opóźnia wykrycie obrazu przez skaner wstępnego wczytywania do momentu, aż te zasoby zostaną w pełni pobrane.

W tym przykładzie wstawianie kodu w tekście ma negatywny wpływ na LCP i ogólną wydajność. Wersja strony, która nie zawiera żadnych elementów wbudowanych, renderuje obraz LCP w około 3,5 sekundy. Strona, która zawiera wszystko w kodzie, nie renderuje obrazu LCP przez nieco ponad 7 sekund.

W tym przypadku chodzi o coś więcej niż tylko skaner wstępnego wczytywania. Wstawianie czcionek w kodzie nie jest dobrą strategią, ponieważ base64 jest nieefektywnym formatem zasobów binarnych. Innym czynnikiem jest to, że zewnętrzne zasoby czcionek nie są pobierane, chyba że CSSOM uzna je za niezbędne. Gdy te czcionki są wstawiane jako base64, są pobierane niezależnie od tego, czy są potrzebne na bieżącej stronie.

Czy wstępne wczytywanie może poprawić sytuację? Jasne. Możesz wstępnie wczytać obraz LCP i skrócić czas LCP, ale przeładowanie kodu HTML, który może nie być możliwy do zapisania w pamięci podręcznej, zasobami wbudowanymi ma inne negatywne konsekwencje dla wydajności. Ten wzorzec ma też wpływ na pierwsze wyrenderowanie treści (FCP). W wersji strony, na której nic nie jest wstawione, FCP wynosi około 2,7 sekundy. W wersji, w której wszystko jest wstawione, FCP wynosi około 5,8 sekundy.

Zachowaj szczególną ostrożność podczas wstawiania elementów do kodu HTML, zwłaszcza zasobów zakodowanych w formacie base64. Zwykle nie jest to zalecane, z wyjątkiem bardzo małych zasobów. Wstawiaj jak najmniej, ponieważ zbyt wiele wstawień to igranie z ogniem.

Renderowanie znaczników za pomocą kodu JavaScript po stronie klienta

Nie ma wątpliwości, że JavaScript wpływa na szybkość strony. Deweloperzy nie tylko polegają na nim, aby zapewnić interaktywność, ale też mają tendencję do polegania na nim w celu dostarczania samych treści. W pewnym sensie ułatwia to pracę deweloperom, ale korzyści dla deweloperów nie zawsze przekładają się na korzyści dla użytkowników.

Jednym ze wzorców, który może uniemożliwić działanie skanera wstępnego wczytywania, jest renderowanie znaczników za pomocą kodu JavaScript po stronie klienta:

Wodospad sieciowy WebPageTest przedstawiający podstawową stronę z obrazami i tekstem renderowaną całkowicie po stronie klienta w języku JavaScript. Ponieważ znaczniki są zawarte w kodzie JavaScript, skaner wstępnego wczytywania nie może wykryć żadnych zasobów. Wszystkie zasoby są dodatkowo opóźnione ze względu na dodatkowy czas sieci i przetwarzania, którego wymagają platformy JavaScript.
Rys. 14. Wykres kaskadowy sieci WebPageTest strony internetowej renderowanej po stronie klienta, uruchomionej w Chrome na urządzeniu mobilnym z symulowanym połączeniem 3G. Ponieważ treść jest zawarta w kodzie JavaScript i do renderowania wymaga platformy, zasób obrazu w znacznikach renderowanych po stronie klienta jest ukryty przed skanerem wstępnego wczytywania. Odpowiednik renderowany po stronie serwera jest przedstawiony na rys. 9.

Gdy ładunki znaczników są zawarte w kodzie JavaScript i renderowane w całości przez ten kod w przeglądarce, wszystkie zasoby w tych znacznikach są niewidoczne dla skanera wstępnego wczytywania. Opóźnia to wykrywanie ważnych zasobów, co z pewnością wpływa na LCP. W tych przykładach żądanie obrazu LCP jest znacznie opóźnione w porównaniu z odpowiednikiem renderowanym po stronie serwera, który nie wymaga JavaScriptu.

To nieco odbiega od tematu tego artykułu, ale efekty renderowania znaczników na kliencie wykraczają daleko poza ominięcie skanera wstępnego wczytywania. Po pierwsze, wprowadzenie JavaScriptu do obsługi funkcji, która go nie wymaga, powoduje niepotrzebne wydłużenie czasu przetwarzania, co może mieć wpływ na interakcję do kolejnego wyrenderowania (INP). Renderowanie bardzo dużych ilości znaczników po stronie klienta może generować długie zadania w porównaniu z tą samą ilością znaczników wysyłanych przez serwer. Powodem tego – oprócz dodatkowego przetwarzania, którego wymaga JavaScript – jest to, że przeglądarki przesyłają znaczniki z serwera i dzielą renderowanie na fragmenty w taki sposób, że zwykle ogranicza to długie zadania. Z kolei znaczniki renderowane po stronie klienta są obsługiwane jako pojedyncze, monolityczne zadanie, co może mieć wpływ na INP strony.

Rozwiązanie w tym przypadku zależy od odpowiedzi na pytanie: czy istnieje powód, dla którego znaczniki strony nie mogą być dostarczane przez serwer, tylko muszą być renderowane po stronie klienta? Jeśli odpowiedź brzmi „nie”, należy rozważyć renderowanie po stronie serwera (SSR) lub statycznie generowane znaczniki, ponieważ pomoże to skanerowi wstępnego wczytywania wykryć i pobrać ważne zasoby z wyprzedzeniem.

Jeśli Twoja strona potrzebuje JavaScriptu, aby dodać funkcje do niektórych części znaczników, możesz to zrobić za pomocą SSR, używając czystego JavaScriptu lub hydratacji, aby uzyskać najlepsze rezultaty.

Pomóż skanerowi wstępnego wczytywania pomóc Tobie

Skaner wstępnego wczytywania to bardzo skuteczna optymalizacja przeglądarki, która pomaga szybciej wczytywać strony podczas uruchamiania. Unikając wzorców, które uniemożliwiają wcześniejsze wykrywanie ważnych zasobów, nie tylko ułatwiasz sobie programowanie, ale też tworzysz lepsze wrażenia użytkowników, co przełoży się na lepsze wyniki w przypadku wielu wskaźników, w tym niektórych Web Vitals.

Podsumowując, oto najważniejsze informacje z tego posta:

  • Skaner wstępnego wczytywania przeglądarki to dodatkowy parser HTML, który skanuje przed głównym, jeśli jest on zablokowany, aby wykryć zasoby, które można pobrać wcześniej.
  • Skaner wstępnego wczytywania nie może wykryć zasobów, które nie są obecne w znacznikach dostarczonych przez serwer w początkowym żądaniu nawigacji. Skaner wstępnego wczytywania może zostać pominięty m.in. w tych przypadkach:
    • Wstrzykiwanie zasobów do DOM za pomocą JavaScriptu, niezależnie od tego, czy są to skrypty, obrazy, arkusze stylów czy inne elementy, które lepiej byłoby umieścić w początkowym ładunku znaczników z serwera.
    • Leniwe ładowanie obrazów lub elementów iframe w części strony widocznej na ekranie za pomocą rozwiązania JavaScript.
    • renderowanie znaczników na kliencie, które mogą zawierać odwołania do zasobów podrzędnych dokumentu, za pomocą JavaScriptu;
  • Skaner wstępnego wczytywania skanuje tylko kod HTML. Nie sprawdza zawartości innych zasobów, zwłaszcza CSS, które mogą zawierać odniesienia do ważnych zasobów, w tym kandydatów do LCP.

Jeśli z jakiegoś powodu nie możesz uniknąć wzorca, który negatywnie wpływa na zdolność skanera wstępnego wczytywania do przyspieszania ładowania, rozważ użycie wskazówki dotyczącej zasobów rel=preload. Jeśli używasz rel=preload, przetestuj tę funkcję w narzędziach laboratoryjnych, aby upewnić się, że działa zgodnie z oczekiwaniami. Nie wczytuj wstępnie zbyt wielu zasobów, ponieważ jeśli nadasz priorytet wszystkim, żaden nie będzie go miał.

Zasoby