Nie walcz ze skanerem wstępnego wczytywania przeglądarki

Dowiedz się, czym jest skaner wstępnego wczytywania w przeglądarce, jak pomaga on w zwiększaniu wydajności i jak możesz go uniknąć.

Jednym z pomijanych aspektów optymalizacji szybkości strony jest znajomość wewnętrznej budowy przeglądarki. Przeglądarki wprowadzają pewne optymalizacje, aby poprawić wydajność w sposób, którego my, jako deweloperzy, nie możemy osiągnąć, ale tylko wtedy, gdy te optymalizacje nie zostaną przypadkowo zablokowane.

Jedną z optymalizacji przeglądarki wewnętrznej, którą warto poznać, jest skaner wstępnego ładowania przeglądarki. Z tego artykułu dowiesz się, jak działa skaner wstępnego wczytywania i jak uniknąć problemów z jego działaniem.

Co to jest skaner wstępnego wczytania?

Każda przeglądarka ma podstawowy parsujący HTML, który znakuje znaczniki nieprzetworzone i przetwarza je w model obiektów. Wszystko to trwa do momentu, gdy parsowanie zostanie wstrzymane po znalezieniu zasobu blokującego, takiego jak wczytana szata wczytana za pomocą elementu <link> lub skrypt wczytany za pomocą elementu <script> bez atrybutu async lub defer.

Schemat działania parsowania HTML
Ryc. 1. Diagram przedstawiający sposób blokowania głównego modułu parsowania HTML w przeglądarce. W tym przypadku parser napotyka element <link> dla zewnętrznego pliku CSS, który uniemożliwia przeglądarce przeanalizowanie reszty dokumentu (a nawet jego renderowanie), dopóki plik CSS nie zostanie pobrany i przeanalizowany.

W przypadku plików CSS renderowanie jest blokowane, aby zapobiec błyskawicznemu wyświetlaniu treści bez stylów (FOUC), czyli sytuacji, w której na krótko widoczna jest wersja strony bez stylów, zanim zostaną one zastosowane.

Strona główna web.dev bez stylizacji (po lewej) i ze stylizacją (po prawej).
Rysunek 2. Symulowany przykład funkcji ostrzegania o zmianach Po lewej stronie znajduje się strona główna web.dev bez stylów. Po prawej stronie znajduje się ta sama strona ze stylami. Stan bez stylów może wystąpić w mgnieniu oka, jeśli przeglądarka nie blokuje renderowania podczas pobierania i przetwarzania arkusza stylów.

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

Dzieje się tak, ponieważ przeglądarka nie może mieć pewności, czy dany skrypt zmodyfikuje DOM, gdy główny parsarz HTML nadal wykonuje swoje zadanie. Dlatego częstą praktyką jest wczytywanie kodu JavaScript na końcu dokumentu, aby efekty zablokowanego analizowania i renderowania były marginalne.

To wystarczające powody, dla których przeglądarka powinna blokować zarówno analizowanie, jak i renderowanie. Blokowanie któregokolwiek z tych ważnych kroków jest jednak niepożądane, ponieważ może opóźnić odkrywanie innych ważnych zasobów. Na szczęście przeglądarki robią, co w ich mocy, aby ograniczyć te problemy za pomocą dodatkowego analizatora HTML, zwanego skanerem wstępnego ładowania.

Schemat pokazujący działanie głównego analizatora HTML (po lewej) i skanera wstępnego wczytywania (po prawej), który jest dodatkowym analizatorem HTML.
Rys. 3. Schemat pokazujący, jak skaner wstępnego wczytania działa równolegle z głównym parsowaniem kodu HTML w celu spekulatywnego wczytania zasobów. W tym przypadku główny parsujący HTML jest zablokowany, ponieważ wczytuje i przetwarza CSS, zanim zacznie przetwarzać znaczniki obrazu w elemencie <body>. Skaner wstępnego wczytywania może jednak zajrzeć do nieprzetworzonego znacznika, aby znaleźć zasób obrazu i rozpocząć jego wczytywanie, zanim zostanie odblokowany główny parsujący HTML.

Rola skanera wstępnego jest spekulatywna, co oznacza, że skaner sprawdza nieprzetworzony znacznik, aby znaleźć zasoby do pobrania, zanim główny parsujący HTML je odkryje.

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

Skaner wstępnego wczytywania istnieje z powodu zablokowanego renderowania i analizowania. Jeśli te 2 problemy z wydajnością nigdy nie wystąpiły, skaner wstępnego wczytania nie będzie zbyt przydatny. Kluczem do określenia, czy strona internetowa korzysta ze skanera wstępnego, są te zjawiska blokowania. Aby to zrobić, możesz wprowadzić sztuczne opóźnienie dla żądań, aby dowiedzieć się, gdzie działa skaner wstępnego ładowania.

Weźmy na przykład tę stronę z tekstem i obrazami z wykorzystaniem arkusza stylów. Ponieważ pliki CSS blokują zarówno renderowanie, jak i analizę, usługa proxy powoduje sztuczne opóźnienie o 2 sekundy dla arkusza stylów. Dzięki temu łatwiej jest sprawdzić w splacie sieciowym, kiedy działa skaner wstępnego ładowania.

Wykres sieci WebPageTest pokazuje sztuczne opóźnienie o 2 sekundy narzucone na arkusz stylów.
Rys. 4. WebPageTest WebPageTest strony internetowej uruchomionej w Chrome na urządzeniu mobilnym z symulowanym połączeniem 3G. Mimo że wczytywanie skryptu zostaje sztucznie opóźnione przez serwer proxy o 2 sekundy, obraz znajdujący się później w pliku danych znaczników jest wykrywany przez skaner wstępnego wczytania.

Jak widać na wykresie kaskadowym, skaner wstępnego załadowania wykrywa element <img> nawet wtedy, gdy renderowanie i analiza dokumentu są zablokowane. Bez tej optymalizacji przeglądarka nie może pobierać danych w okresie blokowania, a więcej żądań zasobów będzie się pojawiać kolejno, a nie równocześnie.

Po przykładzie zabawki przyjrzyjmy się teraz prawdziwym wzorom, w których przypadku skaner wstępnego ładowania może zostać pokonany, oraz temu, jak można to naprawić.

Wstrzyknięte skrypty async

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

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

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

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

Ten wykres WebPageTest pokazuje, że skanowanie wstępne zostało zablokowane przez wstrzyknięcie skryptu.
Rys. 5. Wykres kaskadowy sieci WebPageTest strony internetowej uruchomionej w Chrome na urządzeniu mobilnym z symulowanym połączeniem 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.

Oto, co się tutaj stało:

  1. W 0 sekundzie wysyłany jest dokument główny.
  2. W 1, 4 sekundy dociera pierwszy bajt żądania nawigacji.
  3. W 2, 0 sekundzie następuje żądanie pliku CSS i obrazu.
  4. Ponieważ parsowanie jest zablokowane, wczytywanie arkusza stylów i wbudowany kod JavaScript, który wstrzykuje kod async, pojawia się po tym arkuszu stylów po 2,6 sekundy, funkcja tego kodu nie jest dostępna od razu.

Nie jest to optymalne rozwiązanie, ponieważ żądanie skryptu jest wysyłane dopiero po zakończeniu pobierania arkusza stylów. Dzięki temu skrypt nie zostanie uruchomiony od razu. Z drugiej strony, element <img> jest dostępny w znacznikach dostarczonych przez serwer, więc jest wykrywany przez skaner wstępnego ładowania.

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

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

Oto wynik:

Kaskada sieci WebPageTest pokazująca, jak skrypt asynchroniczny wczytywany za pomocą elementu skryptu HTML jest nadal wykrywany przez skaner wstępnego wczytywania przeglądarki, mimo że podczas pobierania i przetwarzania arkusza stylów blokowany jest główny parsarz HTML przeglądarki.
Rys. 6. Wykres kaskady sieci WebPageTest dla strony internetowej wczytywanej w Chrome na urządzeniu mobilnym z symulowanym połączeniem 3G. Strona zawiera 1 arkusz stylów i 1 element async <script>. Skaner wstępnego wczytywania wykrywa skrypt na etapie blokowania renderowania i wczytuje go równolegle z arkuszy CSS.

Możesz mieć pokusę, by zasugerować, że te problemy można rozwiązać, używając rel=preload. To na pewno zadziała, ale może mieć pewne skutki uboczne. Po co używać elementu rel=preload do rozwiązania problemu, którego można uniknąć, nie wstrzykując elementu <script> do DOM?

Kaskada WebPageTest pokazująca, jak wskaźnik zasobu rel=preload jest używany do promowania wykrywania asynchronicznie wstrzykniętego skryptu, ale 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 z symulowanym połączeniem 3G. Strona zawiera pojedynczy arkusz stylów i wstrzyknięty skrypt async, ale skrypt async jest wstępnie wczytany, aby zapewnić jego wcześniejsze wykrycie.

Wczytywanie z wyprzedzeniem „rozwiązuje” ten problem, ale powoduje pojawienie się nowego: skrypt async w pierwszych 2 demonstracjach – mimo że jest wczytywany w ramach <head> – jest wczytywany z priorytetem „Niski”, podczas gdy arkusz stylów jest wczytywany z priorytetem „Najwyższy”. W ostatnim pokazie, w którym skrypt async jest wstępnie wczytany, wczytywanie arkusza stylów nadal ma priorytet „Najwyższy”, ale priorytet skryptu został podwyższony do „Wysoki”.

Gdy priorytet zasobu jest podwyższony, przeglądarka przydziela mu więcej przepustowości. Oznacza to, że nawet jeśli szata ma najwyższy priorytet, podwyższony priorytet skryptu może spowodować konflikt przepustowości. Może to być spowodowane wolnym połączeniem lub dużymi zasobami.

Odpowiedź jest prosta: jeśli skrypt jest potrzebny podczas uruchamiania, nie pokonuj skanera wstępnego ładowania, wstrzykując go do DOM. W razie potrzeby eksperymentuj z umieszczaniem elementów <script> oraz z atrybutami takimi jak deferasync.

Leniwe ładowanie za pomocą JavaScriptu

Łagodne wczytywanie to świetna metoda oszczędzania danych, która jest często stosowana w przypadku obrazów. Czasami jednak ładowanie opóźnione jest nieprawidłowo stosowane do obrazów, które są „powyżej zagięcia”.

Powoduje to potencjalne problemy z wykrywalnością zasobów w przypadku skanowania wstępnego i może niepotrzebnie wydłużać czas wykrywania odwołania do obrazu, jego pobierania, dekodowania i prezentowania. Weźmy na przykład ten znacznik obrazu:

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

Użycie prefiksu data- jest typowym wzorcem w opóźnionych ładowarkach opartych na JavaScript. Gdy obraz zostanie przewinięty do widoku, opóźniony ładowacz usunie prefiks data-, co oznacza, że w poprzednim przykładzie data-src stanie się src. Ta aktualizacja powoduje pobranie zasobu przez przeglądarkę.

Ten wzór nie stanowi problemu, dopóki nie zostanie zastosowany do obrazów, które znajdują się w widoku podczas uruchamiania. Skaner wstępnego wczytania nie odczytuje atrybutu data-src w taki sam sposób jak atrybutu src (lub srcset), więc odniesienie do obrazu nie zostanie wcześniej wykryte. Co gorsza, obraz jest wczytywany dopiero po pobraniu, skompilowaniu i wykonywaniu kodu JavaScript.

Wykres sieci WebPageTest pokazujący, jak obraz wczytywany z opóźnieniem, który jest widoczny w widoku podczas uruchamiania, jest koniecznie opóźniony, ponieważ skaner wstępnego wczytania przeglądarki nie może znaleźć zasobu obrazu i ładuje się dopiero wtedy, gdy wczytuje się kod JavaScript wymagany do wczytywania z opóźnieniem. obraz jest odkrywany znacznie później, niż powinien;
Ryc. 8. Wykres kaskadowy sieci WebPageTest strony internetowej uruchomionej w Chrome na urządzeniu mobilnym z symulowanym połączeniem 3G. Zasób obrazu jest niepotrzebnie ładowany z opóźnieniem, mimo że jest widoczny w widocznym obszarze podczas uruchamiania. To uniemożliwia działanie skanera wstępnego ładowania i powoduje niepotrzebne opóźnienie.

W zależności od rozmiaru obrazu, który może zależeć od rozmiaru widocznego obszaru, może to być element kwalifikujący się do największego wyrenderowania treści (LCP). Gdy skaner wstępnego wczytywania nie może z wyprzedzeniem pobrać zasobu obrazu(np. w momencie, w którym blokowanie renderowania przez arkusz stylów strony), wartość LCP się pogarsza.

Rozwiązaniem jest zmiana znaczników obrazu:

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

Jest to optymalny wzór dla obrazów, które są widoczne w widoku podczas uruchamiania, ponieważ skaner wstępnego ładowania szybciej wykryje i pobierze zasób obrazów.

Wykres kaskady sieci WebPageTest przedstawiający scenariusz wczytywania obrazu w widocznym obszarze podczas uruchamiania. Obraz nie jest ładowany z opóźnieniem, co oznacza, że nie zależy od skryptu, który ma być wczytany, a to z kolei oznacza, że skaner wstępnego wczytania może go wykryć wcześniej.
Ryc. 9. Wykres kaskadowy sieci WebPageTest strony internetowej uruchomionej w Chrome na urządzeniu mobilnym z symulowanym połączeniem 3G. Skaner wstępnego załadowania wykrywa zasób obrazu przed rozpoczęciem wczytywania kodu CSS i JavaScriptu, co daje przeglądarce przewagę w wczytywaniu.

W tym uproszczonym przykładzie wynik to poprawa LCP o 100 ms przy wolnym połączeniu. Może się to wydawać niewielką poprawą, ale jest to szybkie rozwiązanie, które wymaga zmiany znaczników, a większość stron internetowych jest bardziej skomplikowana niż te przykłady. Oznacza to, że kandydaci do LCP mogą konkurować o przepustowość z wielkimi zasobami, dlatego takie optymalizacje stają się coraz ważniejsze.

Obrazy tła w kodzie CSS

Pamiętaj, że skaner wstępnego załadowania przeglądarki skanuje oznaczenia. Nie skanuje innych typów zasobów, takich jak CSS, które mogą wymagać pobierania obrazów odwołujących się do właściwości background-image.

Podobnie jak w przypadku HTML, przeglądarki przetwarzają kod CSS w swój własny model obiektów, zwany CSSOM. Jeśli podczas tworzenia obiektu CSSOM zostaną wykryte zasoby zewnętrzne, są one żądane w momencie ich wykrycia, a nie przez skaner wstępnego ładowania.

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

Wykres osi czasu sieci WebPageTest przedstawiający stronę z elementem LCP wczytywanym z arkusza CSS za pomocą właściwości background-image. Ponieważ obraz kandydat na LCP jest zasobem typu, którego nie może skanować skaner wstępnego wczytania przeglądarki, wczytywanie zasobu jest opóźnione do momentu pobrania i przetworzenia pliku CSS, co opóźnia czas renderowania obrazu kandydata na LCP.
Rys. 10. Wykres kaskadowy sieci WebPageTest strony internetowej uruchomionej w Chrome na urządzeniu mobilnym z symulowanym połączeniem 3G. Identyfikator LCP strony to element z właściwością CSS background-image (wiersz 3). Przetwarzanie żądanego obrazu rozpoczyna się dopiero po znalezieniu go przez parsujący CSS.

W takim przypadku skaner wstępnego ładowania nie został tak naprawdę pokonany, tylko nie był używany. Mimo to, jeśli kandydat na element LCP na stronie pochodzi z usługi background-image CSS, warto go wstępnie załadować:

<!-- 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">

Ten rel=preload jest niewielki, ale pomaga przeglądarce szybciej wykryć obraz:

Wykres sieci WebPageTest pokazujący obraz tła CSS (który jest kandydatem na LCP) wczytywany znacznie wcześniej dzięki zastosowaniu wskazówki rel=preload. Czas LCP skraca 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. Identyfikator LCP strony to element z właściwością CSS background-image (wiersz 3). Wskazówka rel=preload pomaga przeglądarce wykryć obraz około 250 ms szybciej niż bez niej.

Dzięki podpowiedzi rel=preload kandydat na element LCP jest odkrywany wcześniej, co skraca czas LCP. Ten podpowiedź może pomóc w rozwiązaniu tego problemu, ale lepszym rozwiązaniem może być ocena, czy obraz kandydujący do LCP musi być wczytany z CSS. Dzięki tagowi <img> możesz lepiej kontrolować wczytywanie obrazu odpowiedniego dla widoku, a jednocześnie umożliwić skanowanie wstępne skanerom.

Wstawianie zbyt wielu zasobów

Wstawianie to umieszczanie zasobu w kodzie HTML. Możesz wstawiać w treści style w elementach <style>, skrypty w elementach <script> i praktycznie dowolne inne zasoby za pomocą kodowania base64.

Wstawianie zasobów może być szybsze niż ich pobieranie, ponieważ nie jest wysyłane osobne żądanie. Jest ona widoczna w dokumencie i wczytuje się natychmiast. Ma on jednak istotne wady:

  • Jeśli nie przechowujesz w pamięci podręcznej kodu HTML (a nie możesz tego zrobić, gdy odpowiedź HTML jest dynamiczna), zaszyte zasoby nigdy nie są przechowywane w pamięci podręcznej. Wpływa to na wydajność, ponieważ zaszyte zasoby nie mogą być używane wielokrotnie.
  • Nawet jeśli możesz przechowywać w pamięci podręcznej kod HTML, wbudowane zasoby nie są udostępniane między dokumentami. Ogranicza to skuteczność pamięci podręcznej w porównaniu z plikami zewnętrznymi, które można przechowywać w pamięci podręcznej i ponownie używać w całym źródle.
  • Jeśli wstawiasz zbyt wiele elementów, skanowanie wstępne opóźnia wykrywanie zasobów w dalszej części dokumentu, ponieważ pobieranie tego dodatkowego wstawionego elementu zajmuje więcej czasu.

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

Wykres kaskady sieci WebPageTest strony z zewnętrznym plikiem CSS zawierającym odniesienia do 4 czcionek. Obraz kandydujący do LCP zostanie w odpowiednim czasie wykryty przez skaner wstępnego ładowania.
Rys. 12. Wykres kaskadowy sieci WebPageTest strony internetowej uruchomionej w Chrome na urządzeniu mobilnym z symulowanym połączeniem 3G. Kandydat na LCP strony to obraz wczytywany z elementu <img>, ale jest on wykrywany przez skaner wstępnego wczytania, ponieważ czcionki i pliki CSS wymagane do wczytania strony znajdują się w oddzielnych zasobach, co nie opóźnia działania skanera wstępnego wczytania.

Co się stanie, jeśli CSS iwszystkie czcionki są wbudowane jako zasoby base64?

Wykres kaskady sieci WebPageTest strony z zewnętrznym plikiem CSS zawierającym odniesienia do 4 czcionek. Skaner wstępnego wczytania znacznie opóźnia wykrywanie obrazu LCP .
Rys. 13. Wykres kaskadowy sieci WebPageTest strony internetowej uruchomionej w Chrome na urządzeniu mobilnym z symulowanym połączeniem 3G. Kandydat na LCP strony to obraz wczytywany z elementu <img>, ale wstawienie w elementie `` powoduje, że skanowanie wstępne nie może wykryć obrazu, dopóki nie zostaną całkowicie pobrane wszystkie zasoby czcionek.

W tym przykładzie wstawienie kodu inline negatywnie wpływa na LCP, a także ogólną wydajność. Wersja strony, która nie zawiera żadnych elementów wstawianych, renderuje obraz LCP w około 3,5 sekundy. Strona, która wyświetla wszystko w ramce, nie renderuje obrazu LCP do czasu, gdy upłynie ponad 7 sekund.

W tym przypadku chodzi o coś więcej niż tylko skaner wstępnego wczytania. Wstawianie czcionek w dokumentie nie jest dobrym rozwiązaniem, ponieważ format base64 jest nieefektywnym formatem zasobów binarnych. Kolejnym czynnikiem jest to, że zewnętrzne zasoby czcionek nie są pobierane, chyba że zostaną uznane za niezbędne przez CSSOM. Gdy te czcionki są wstawiane w formacie base64, są pobierane niezależnie od tego, czy są potrzebne na bieżącej stronie.

Czy w takim przypadku załadowanie wstępne może pomóc? Jasne. Możesz wstępnie wczytać obraz LCP i skracać czas LCP, ale nadmierne rozszerzanie kodu HTML, który nie może być przechowywany w pamięci podręcznej, za pomocą wstawionych zasobów ma inne negatywne konsekwencje dla wydajności. Ten wzór ma również wpływ na pierwsze wyrenderowanie treści (FCP). W wersji strony, w której nie ma żadnych wstawionych elementów, FCP wynosi około 2,7 sekundy. W wersji, w której wszystko jest wstawione, FCP wynosi około 5,8 sekund.

Bardzo ostrożnie podchodź do 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 elementów, ponieważ umieszczanie zbyt wielu elementów w tekście może przynieść więcej szkody niż pożytku.

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

Nie ma wątpliwości, że JavaScript ma wpływ na szybkość wczytywania strony. Deweloperzy polegają na nim nie tylko w zakresie interakcji, ale też w zakresie dostarczania 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 z wzorów, który może uniemożliwić działanie skanera wstępnego wczytywania, jest renderowanie znaczników za pomocą kodu JavaScript po stronie klienta:

Sieć WebPageTest w postaci wykresu kaskadowego przedstawiającego podstawową stronę z obrazami i tekstem renderowanym całkowicie po stronie klienta w JavaScript. Skrypt do skanowania wstępnego nie może wykryć żadnych zasobów, ponieważ znaczniki są zawarte w JavaScript. Wszystkie zasoby są dodatkowo opóźnione z powodu dodatkowego czasu potrzebnego na przetwarzanie i przesyłanie danych przez sieć, który wymagają frameworki JavaScript.
Ryc. 14. Wykres kaskadowy sieci WebPageTest strony internetowej renderowanej po stronie klienta, która działa w Chrome na urządzeniu mobilnym z symulowanym połączeniem 3G. Treść jest zawarta w JavaScript i korzysta z ramy do renderowania, dlatego zasób obrazów w oznaczeniu renderowanym po stronie klienta jest ukryty przed skanerem wstępnego ładowania. Odpowiednią wersję z renderowaniem po stronie serwera przedstawia rys. 9.

Gdy dane znaczników są zawarte w JavaScript i w pełni renderowane przez niego w przeglądarce, wszystkie zasoby w tym znaczniku są w praktyce niewidoczne dla skanera wstępnego. Opóźnia to wykrywanie ważnych zasobów, co z pewnością wpływa na LCP. W przypadku tych przykładów żądanie obrazu LCP jest znacznie opóźnione w porównaniu z odpowiednim obrazem renderowanym na serwerze, który nie wymaga uruchamiania JavaScriptu.

To trochę odbiega od tematu tego artykułu, ale efekty renderowania znaczników na kliencie wykraczają daleko poza pokonywaniem skanera wstępnego ładowania. Po pierwsze, wprowadzenie JavaScriptu do obsługi funkcji, która go nie wymaga, powoduje niepotrzebne przetwarzanie, co może wpływać na czas od interakcji do kolejnego wyrenderowania (INP). Renderowanie bardzo dużych ilości znaczników na kliencie powoduje dłuższe zadania niż w przypadku takiej samej ilości znaczników wysyłanych przez serwer. Powodem tego, poza dodatkowym przetwarzaniem wymaganym przez JavaScript, jest to, że przeglądarki przesyłają znaczniki ze serwera i dzielą renderowanie na części w taki sposób, aby ograniczać czas wykonywania długich zadań. Z drugiej strony znaczniki renderowane po stronie klienta są obsługiwane jako pojedyncze, monolityczne zadanie, które może wpływać na INP strony.

Rozwiązanie tego problemu zależy od odpowiedzi na to pytanie: Czy istnieje powód, dla którego znacznik strony nie może być dostarczony przez serwer, a nie renderowany po stronie klienta? Jeśli odpowiedź na to pytanie brzmi „nie”, należy rozważyć renderowanie po stronie serwera (SSR) lub generowanie znaczników statycznych, o ile to możliwe, ponieważ pomoże to skanerowi w poprzedzającym pobieraniu ważnych zasobów.

Jeśli Twoja strona musi używać JavaScriptu do dołączania funkcji do niektórych części znacznika strony, nadal możesz to robić za pomocą SSR, korzystając z tradycyjnego JavaScriptu lub hydratacji, aby połączyć zalety obu tych metod.

Jak korzystać z skanera wstępnego

Skaner wstępnego wczytywania to bardzo skuteczna optymalizacja przeglądarki, która pomaga szybciej wczytywać strony podczas uruchamiania. Unikanie schematów, które uniemożliwiają wcześniejsze wykrywanie ważnych zasobów, nie tylko upraszcza proces tworzenia, ale też zapewnia lepsze wrażenia użytkowników, co przekłada się na lepsze wyniki w wielu rodzajach danych, w tym w przypadku niektórych wskaźników internetowych.

Oto podsumowanie tego posta:

  • Skaner wstępnego wczytywania przeglądarki to dodatkowy parsujący HTML, który skanuje przed głównym, jeśli jest zablokowany, aby optymistycznie wykrywać zasoby, które może pobrać wcześniej.
  • Skaner wstępnego ładowania 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żna obejść na różne sposoby, m.in.:
    • Wstrzykiwanie zasobów do DOM za pomocą JavaScriptu, np. skryptów, obrazów, arkuszy stylów lub innych elementów, które lepiej byłoby umieścić w pierwotnym ładunku znaczników ze strony serwera.
    • wczytywanie opóźnione obrazów i iframe’ów znajdujących się powyżej obszaru widocznego za pomocą rozwiązania JavaScript;
    • Renderowanie znaczników po stronie klienta, które mogą zawierać odwołania do podzasobów dokumentu za pomocą JavaScriptu.
  • Skaner wstępnego załadowania 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 jakiegokolwiek powodu nie możesz uniknąć wzoru, który negatywnie wpływa na zdolność skanera wstępnego wczytywania do przyspieszania wczytywania, skorzystaj z wskazówek dotyczących zasobów rel=preload. Jeśli używasz narzędzia rel=preload, przetestuj je w narzędziach laboratoryjnych, aby upewnić się, że działają zgodnie z oczekiwaniami. Nie wczytuj też zbyt wielu zasobów w tle, ponieważ jeśli wszystko będzie miało najwyższy priorytet, żadne z nich go nie będzie miało.

Zasoby

Baner powitalny z Unsplash autorstwa Mohammad Rahmani .