Ścieżka krytyczna

Ścieżka krytyczna renderowania to zbiór kroków, które muszą zostać wykonane, zanim strona internetowa zacznie się renderować w przeglądarce. Aby renderować strony, przeglądarki potrzebują samego dokumentu HTML oraz wszystkich kluczowych zasobów niezbędnych do jego renderowania.

Przekazywanie dokumentu HTML do przeglądarki zostało omówione w poprzednim module „Ogólne uwagi dotyczące wydajności kodu HTML”. W tym module przyjrzymy się jednak temu, co przeglądarka robi po pobraniu dokumentu HTML w celu wyrenderowania strony.

Renderowanie progresywne

Internet jest rozpowszechniany w zależności od potrzeb. W przeciwieństwie do aplikacji natywnych, które są instalowane przed użyciem, przeglądarki nie mogą polegać na tym, że witryny mają wszystkie zasoby potrzebne do wyrenderowania strony. Dlatego przeglądarki bardzo dobrze radzą sobie z renderowaniem stron stopniowo. Aplikacje natywne zwykle mają fazę instalacji, a potem fazę działania. W przypadku stron internetowych i aplikacji internetowych granice między tymi 2 fazami są znacznie mniej wyraźne, a przeglądarki zostały zaprojektowane z uwzględnieniem tej kwestii.

Gdy przeglądarka ma zasoby do renderowania strony, zwykle zaczyna to robić. Wybór polega więc na tym, kiedy to zrobić: kiedy jest za wcześnie?

Jeśli przeglądarka renderuje stronę tak szybko, jak to możliwe, gdy ma tylko kod HTML, ale nie ma jeszcze kodu CSS ani niezbędnego kodu JavaScript, strona może przez chwilę wyglądać nieprawidłowo i znacznie się zmienić przed ostatecznym renderowaniem. Jest to gorsze rozwiązanie niż wyświetlanie pustego ekranu przez pewien czas, aż przeglądarka uzyska więcej zasobów potrzebnych do wstępnego renderowania, co zapewni większą wygodę użytkownikom.

Jeśli jednak przeglądarka będzie czekać na wszystkie zasoby zamiast renderować je sekwencyjnie, użytkownik będzie musiał długo czekać. Często jest to zbędne, ponieważ strona była gotowa do użycia znacznie wcześniej.

Przeglądarka musi wiedzieć, na jaką minimalną liczbę zasobów powinna czekać, aby uniknąć wyświetlania wyraźnie uszkodzonego interfejsu. Z drugiej strony przeglądarka nie powinna czekać dłużej niż to konieczne, zanim wyświetli użytkownikowi treści. Sekwencja kroków wykonywanych przez przeglądarkę przed wykonaniem początkowego renderowania nosi nazwę krytycznej ścieżki renderowania.

Poznanie ścieżki renderowania krytycznego może pomóc w zwiększeniu wydajności witryny, ponieważ pozwoli Ci uniknąć blokowania początkowego renderowania strony na dłużej niż to konieczne. Jednocześnie ważne jest, aby nie dopuścić do renderowania zbyt wcześnie, usuwając z ścieżki renderowania krytycznych zasobów niezbędnych do wstępnego renderowania.

Ścieżka renderowania (krytyczna)

Ścieżka renderowania obejmuje te kroki:

  • Tworzenie obiektowego modelu dokumentu (DOM) na podstawie kodu HTML.
  • Tworzenie modelu obiektów CSS (CSSOM) na podstawie kodu CSS.
  • stosowanie kodu JavaScript, który zmienia DOM lub CSSOM;
  • Tworzenie drzewa renderowania na podstawie DOM i CSSOM.
  • Wykonuj na stronie operacje związane ze stylem i układem, aby sprawdzić, które elementy pasują do siebie.
  • malować piksele elementów w pamięci;
  • Składaj piksele, jeśli się nakładają.
  • Fizycznie wyświetla wszystkie uzyskane piksele na ekranie.
Proces renderowania od kodu HTML i CSS do wyświetlania pikseli.
Proces renderowania, jak opisano na poprzedniej liście.

Użytkownik zobaczy treści na ekranie dopiero po wykonaniu wszystkich tych czynności.

Proces renderowania jest powtarzany kilka razy. Początkowe renderowanie uruchamia ten proces, ale gdy dostępnych jest więcej zasobów wpływających na renderowanie strony, przeglądarka ponownie uruchomi ten proces (lub tylko jego części), aby zaktualizować to, co widzi użytkownik. Ścieżka krytyczna renderowania skupia się na procesie opisanym wcześniej w przypadku początkowego renderowania i zależy od krytycznych zasobów, które są do niego potrzebne.

Jakie zasoby znajdują się na ścieżce renderowania krytycznego?

Zanim przeglądarka przejdzie do początkowego renderowania, musi poczekać na pobranie niektórych kluczowych zasobów. Znajdziesz tam:

  • Część kodu HTML.
  • Blokowanie renderowania przez kod CSS w elemencie <head>.
  • Kod JavaScript blokujący renderowanie w elemencie <head>.

Kluczowym punktem jest to, że przeglądarka przetwarza kod HTML w trybie strumieniowym. Gdy przeglądarka otrzyma dowolną część kodu HTML strony, zaczyna ją przetwarzać. Przeglądarka może (i często tak się dzieje) zdecydować się na renderowanie jeszcze przed otrzymaniem reszty kodu HTML strony.

Podczas początkowego renderowania przeglądarka zazwyczaj nie czeka na:

  • cały kod HTML.
  • czcionki;
  • obrazy.
  • Kod JavaScript, który nie blokuje renderowania, poza elementem <head> (np. elementy <script> umieszczone na końcu kodu HTML).
  • CSS, który nie blokuje renderowania, poza elementem <head> lub CSS z wartością atrybutu media, która nie ma zastosowania do bieżącego widoku.

Przeglądarka często traktuje czcionki i obrazy jako treści, które mają być wypełniane podczas kolejnych renderowań strony, więc nie muszą one opóźniać początkowego renderowania. Może to jednak oznaczać, że w początkowym renderowaniu pozostaną puste obszary, ponieważ tekst jest ukryty i czeka na czcionki lub na to, aż będą dostępne obrazy. Jeszcze gorsza sytuacja ma miejsce, gdy nie zarezerwujesz wystarczającej ilości miejsca na określone typy treści, zwłaszcza gdy w kodzie HTML nie podasz wymiarów obrazów. Układ strony może się wtedy zmienić, gdy te treści zostaną załadowane później. Ten aspekt wrażeń użytkownika jest mierzony za pomocą wskaźnika skumulowanego przesunięcia układu (CLS).

Element <head> jest kluczowy dla przetwarzania ścieżki renderowania krytycznego. W następnej sekcji omówimy to bardziej szczegółowo. Optymalizacja zawartości elementu <head> jest kluczowym aspektem skuteczności witryny. Aby zrozumieć ścieżkę renderowania krytycznego, wystarczy wiedzieć, że element <head> zawiera metadane dotyczące strony i jej zasobów, ale nie zawiera żadnych treści, które użytkownik może zobaczyć. Treści widoczne znajdują się w elemencie <body>, który następuje po elemencie <head>. Zanim przeglądarka będzie mogła renderować treści, musi zarówno je wyświetlić, jak i uzyskać informacje o sposobie ich renderowania.

Nie wszystkie zasoby odwołujące się do elementu <head> są jednak niezbędne do początkowego wyrenderowania strony, więc przeglądarka czeka tylko na te, które są. Aby określić, które zasoby znajdują się na krytycznej ścieżce renderowania, musisz wiedzieć, które elementy kodu CSS i JavaScriptu blokują renderowanie i analizę.

Zasoby blokujące renderowanie

Niektóre zasoby są tak ważne, że przeglądarka wstrzymuje renderowanie strony, dopóki nie przetworzy tych zasobów. Domyślnie do tej kategorii należy CSS.

Gdy przeglądarka widzi kod CSS (niezależnie od tego, czy jest to kod inline w elemencie <style>, czy zasób z zewnętrznym odwołaniem określony przez element <link rel=stylesheet href="...">), nie renderuje żadnych innych treści, dopóki nie zakończy się pobieranie i przetwarzanie tego kodu.

To, że zasób blokuje renderowanie, nie oznacza, że uniemożliwia przeglądarce wykonywanie innych czynności. Przeglądarki starają się działać jak najwydajniej, dlatego gdy widzą, że muszą pobrać zasób CSS, wysyłają do niego żądanie i wstrzymuje renderowanie, ale nadal przetwarza pozostałą część kodu HTML i szuka innych zadań do wykonania.

Zasoby blokujące renderowanie, takie jak CSS, które blokowały renderowanie całej strony w momencie wykrycia. Oznacza to, że to, czy niektóre pliki CSS blokują renderowanie, zależy od tego, czy przeglądarka je wykryła. Niektóre przeglądarki (na początku Firefox, a teraz także Chrome) blokują renderowanie treści znajdujących się poniżej zasobu blokującego renderowanie. Oznacza to, że w przypadku ścieżki krytycznych zasobów blokujących renderowanie interesują nas zwykle zasoby blokujące renderowanie w etapie <head>, ponieważ skutecznie blokują renderowanie całej strony.

Nowością jest atrybut blocking=render, dodany do Chrome 105. Dzięki temu deweloperzy mogą wyraźnie oznaczyć element <link>, <script> lub <style> jako blokujący renderowanie, dopóki nie zostanie on przetworzony, ale jednocześnie umożliwić parsującemu kontynuowanie przetwarzania dokumentu.

Zasoby blokujące parsowanie

Zasoby blokujące parsowanie to te, które uniemożliwiają przeglądarce znalezienie innych zadań do wykonania przez kontynuowanie parsowania kodu HTML. Domyślnie kod JavaScript blokuje parsowanie (chyba że jest specjalnie oznaczony jako asynchroniczny lub opóźniony), ponieważ może zmienić DOM lub CSSOM podczas wykonywania. Dlatego przeglądarka nie może przetwarzać innych zasobów, dopóki nie pozna pełnego wpływu żądanego kodu JavaScript na kod HTML strony. Dlatego kod JavaScript synchroniczny blokuje parsowanie.

Zasoby blokujące parsowanie są też skutecznie blokowane przez renderowanie. Ponieważ parsujący nie może przejść dalej niż do zasobu blokującego parsowanie, dopóki nie zostanie on w pełni przetworzony, nie może uzyskać dostępu do treści znajdujących się za nim ani ich wyrenderować. Podczas oczekiwania przeglądarka może renderować dowolny kod HTML otrzymany do tej pory, ale jeśli chodzi o ścieżkę renderowania krytycznego, wszelkie zasoby blokujące parsowanie w <head> oznaczają, że renderowanie wszystkich treści strony jest zablokowane.

Zablokowanie parsowania może mieć ogromny wpływ na wydajność – znacznie większy niż zablokowanie renderowania. Z tego powodu przeglądarki próbują zmniejszyć te koszty, używając dodatkowego parsowania HTML, zwanego skanerem wstępnego wczytania, aby pobierać nadchodzące zasoby, gdy podstawowy parsownik HTML jest zablokowany. Chociaż nie jest to tak dobre rozwiązanie jak przeanalizowanie kodu HTML, pozwala przynajmniej na działanie funkcji sieciowych w przeglądarce przed zablokowanym parsem, co oznacza, że w przyszłości jest mniej prawdopodobne, aby został ponownie zablokowany.

Identyfikowanie zasobów blokujących

Wiele narzędzi do audytu wydajności wykrywa zasoby blokujące renderowanie i analizator. WebPageTest oznacza zasoby blokujące renderowanie pomarańczowym okręgiem po lewej stronie adresu URL zasobu:

Wykres kaskadowy sieci wygenerowany przez WebPageTest Zasoby blokujące parsowanie są oznaczone pomarańczowym okręgiem po lewej stronie adresu URL zasobu, a czas rozpoczęcia renderowania jest oznaczony ciągłą ciemnozieloną linią.
Wykres kaskadowy sieci wygenerowany przez WebPageTest.

Zanim rozpocznie się renderowanie, wszystkie zasoby blokujące renderowanie muszą zostać pobrane i przetworzone. Jest to oznaczone na wykresie kaskadowym ciągłą linią w ciemnozielonym kolorze.

Lighthouse wyróżnia też zasoby blokujące renderowanie, ale w bardziej subtelny sposób i tylko wtedy, gdy zasób rzeczywiście opóźnia renderowanie strony. Może to być przydatne, aby uniknąć wyników fałszywie pozytywnych, gdy minimalizujesz blokowanie renderowania. Uruchomienie tego samego adresu URL strony, co na poprzednim rysunku z WebPageTest, za pomocą Lighthouse pozwala zidentyfikować jako zasób blokujący renderowanie tylko jedną z stron stylów.

Audyt Lighthouse dotyczący eliminowania zasobów blokujących renderowanie. Audyt pokazuje zasoby, które blokują renderowanie, oraz czas trwania tego blokowania.
Audyt Lighthouse dotyczący eliminowania zasobów blokujących renderowanie.

Optymalizacja krytycznej ścieżki renderowania

Optymalizacja ścieżki renderowania krytycznego polega na skróceniu czasu potrzebnego na otrzymanie kodu HTML (reprezentowanego przez dane Czas do pierwszego bajta (TTFB)), jak szczegółowo opisano w poprzednim module, oraz na ograniczeniu wpływu zasobów blokujących renderowanie. Te pojęcia omawiamy w kolejnych modułach.

Krytyczna ścieżka renderowania treści

Przez długi czas ścieżka krytyczna renderowania dotyczyła tylko początkowego renderowania. Pojawiły się jednak nowe dane oparte na użytkownikach dotyczące wydajności strony internetowej, co powoduje pewne wątpliwości, czy punkt końcowy ścieżki renderowania krytycznego powinien być pierwszym wyrenderowaniem czy jednym z późniejszych wyrenderowań z większą ilością treści.

Innym sposobem jest skupienie się na czasie do największego wyrenderowania treści (LCP) lub nawet pierwszego wyrenderowania treści (FCP) w ramach ścieżki renderowania treści (lub ścieżki kluczowej, jak ją czasem nazywają inni). W takim przypadku może być konieczne uwzględnienie zasobów, które niekoniecznie są blokujące (jak to było w przypadku typowej definicji ścieżki renderowania krytycznego), ale są niezbędne do renderowania treści.

Niezależnie od tego, jak definiujesz pojęcie „krytyczne”, warto wiedzieć, co opóźnia początkowe renderowanie i kluczowe treści. Pierwszy obraz mierzy pierwszą możliwą możliwość wyrenderowania czegokolwiek dla użytkownika. W idealnym przypadku powinno to być coś znaczącego, a nie na przykład kolor tła. Jednak nawet jeśli nie ma treści, to nadal warto coś wyświetlić użytkownikowi. Jest to argument za pomiarem krytycznej ścieżki renderowania w tradycyjnym rozumieniu. Jednocześnie warto też mierzyć, kiedy użytkownikowi wyświetla się główna treść.

Określanie ścieżki renderowania treści

Wiele narzędzi może identyfikować elementy LCP i określać, kiedy są renderowane. Oprócz elementu LCP Lighthouse pomaga też zidentyfikować fazy LCP i czas spędzony na każdej z nich, aby ułatwić Ci określenie, na czym należy się skupić podczas optymalizacji:

Audyt LCP w Lighthouse, który pokazuje element LCP strony i czas spędzony na poszczególnych etapach, takich jak TTFB, opóźnienie ładowania, czas ładowania i opóźnienie renderowania.
Audyt LCP w Lighthouse.

W przypadku bardziej złożonych witryn Lighthouse wyróżnia też łańcuchy krytycznych żądań w ramach osobnego audytu:

Diagram łańcucha żądań krytycznych w Lighthouse, który pokazuje, które zasoby krytyczne są zagnieżdżone w innych zasobach krytycznych, a także łączny czas oczekiwania w łańcuchu żądań krytycznych.
Diagram łańcucha krytycznych żądań w Lighthouse.

Ten audyt Lighthouse sprawdza wszystkie zasoby wczytywane z wysokim priorytetem, więc obejmuje czcionki internetowe i inne treści, które Chrome ustawia jako zasoby o wysokim priorytecie, nawet jeśli nie blokują one renderowania.

Sprawdź swoją wiedzę

Do czego odnosi się ścieżka krytyczna renderowania?

Minimalna liczba zasobów potrzebnych do pełnego wyrenderowania strony.
Spróbuj ponownie.
Minimalna liczba zasobów potrzebnych do początkowego wyrenderowania strony.
Dobrze!

Jakie zasoby są wykorzystywane na ścieżce renderowania krytycznego?

Część kodu HTML.
Dobrze!
Blokowanie renderowania przez kod CSS w elemencie <head>.
Dobrze!
Kod JavaScript blokujący renderowanie w elemencie <head>.
Dobrze!

Dlaczego blokowanie renderowania jest niezbędną częścią renderowania strony?

Aby zapobiec renderowaniu strony w niedostępnym lub uszkodzonym stanie.
Dobrze!
Aby uniemożliwić użytkownikom wyświetlanie strony, dopóki nie zostanie ona w pełni wyrenderowana.
Spróbuj ponownie.

Dlaczego kod JavaScript blokuje parsowanie HTML (zakładając, że atrybuty defer, async lub module nie są określone w elemencie <script>)?

Bez co najmniej jednego z tych atrybutów element <script> blokuje parsowanie i renderowanie.
Dobrze!
Wszystkie pliki JavaScript blokują parser niezależnie od tych atrybutów.
Spróbuj ponownie.
Kod JavaScriptu synchronicznego musi być wykonywany, gdy analizator do niego dotrze, ponieważ może zmienić DOM.
Dobrze!

Następny krok: optymalizacja wczytywania zasobów

W tym module omówiliśmy niektóre zagadnienia teoretyczne dotyczące renderowania strony przez przeglądarkę, a w szczególności to, co jest potrzebne do ukończenia początkowego renderowania strony. W następnym module omówimy optymalizację tej ścieżki renderowania, pokazując, jak optymalizować wczytywanie zasobów.