Optymalizacja największego wyrenderowania treści

Największe wyrenderowanie treści (LCP) to jeden z 3 podstawowych wskaźników internetowych. Wartość ta określa, jak szybko wczytuje się główna treść strony internetowej, w szczególności czas od rozpoczęcia wczytywania strony przez użytkownika do momentu wyrenderowania w widocznym obszarze największego obrazu lub bloku tekstu.

Aby zadbać o wygodę użytkowników, wartość LCP witryny musi wynosić co najmniej 2,5 sekundy w przypadku co najmniej 75% wizyt na stronie.

Dobre wartości LCP to 2,5 sekundy lub mniej, niskie – powyżej 4,0 sekundy, a wszystkie pozostałe wymagają poprawy
Dobra wartość LCP to 2,5 sekundy lub mniej.

Na szybkość ładowania i renderowania strony internetowej może wpływać wiele czynników, a opóźnienia w każdym z nich mogą mieć znaczący wpływ na LCP.

Rzadko się zdarza, by szybkie poprawki w jednej części strony powodowały znaczącą poprawę wskaźnika LCP. Aby poprawić LCP, trzeba przyjrzeć się całemu procesowi wczytywania i zoptymalizować każdy jego etap.

Informacje o wskaźniku LCP

Przed zoptymalizowaniem LCP deweloperzy muszą dowiedzieć się, czy w ich witrynie występuje problem z LCP, a jeśli tak, to w jakim stopniu.

Jest wiele narzędzi do pomiaru LCP, ale nie wszystkie z nich mierzą go w ten sam sposób. Aby zrozumieć rzeczywiste wrażenia użytkowników, musisz zrozumieć, co myślą użytkownicy, a nie jedynie to, co może pokazać narzędzie laboratoryjne, takie jak Lighthouse czy testy lokalne. Te laboratoryjne narzędzia mogą dostarczyć wielu informacji do wyjaśnienia LCP i pomóc w poprawianiu wskaźników, ale same testy laboratoryjne nie są w pełni odzwierciedlane przez użytkowników.

Możesz wyświetlać dane LCP na podstawie prawdziwych użytkowników z zainstalowanych w witrynie narzędzi Real User Monitoring (RUM) lub za pomocą Raportu na temat użytkowania Chrome (CrUX), który zbiera anonimowe dane od prawdziwych użytkowników Chrome z milionów witryn.

Używanie danych raportu na temat użytkowania Chrome w PageSpeed Insights

Narzędzie PageSpeed Insights zapewnia dostęp do danych raportu na temat użytkowania Chrome w sekcji Zobacz, jakie są wrażenia użytkowników. Bardziej szczegółowe dane z modułów znajdziesz w sekcji Diagnozowanie problemów z wydajnością. Zawsze w pierwszej kolejności koncentruj się na danych z raportu CrUX, jeśli są dostępne.

Dane raportu na temat użytkowania Chrome wyświetlane w PageSpeed Insights
Dane na temat użytkowania Chrome pokazane w PageSpeed Insights.

Jeśli raport na temat użytkowania Chrome nie udostępnia danych (np. w przypadku strony z niewystarczającym ruchem, aby uzyskać dane na poziomie strony), możesz uzupełnić ten kod danymi RUM zbieranymi za pomocą interfejsów API JavaScript działających na stronie. Może to też dostarczyć znacznie więcej danych, niż raport CrUX może udostępnić jako publiczny zbiór danych. W dalszej części przewodnika wyjaśnimy, jak zbierać te dane za pomocą JavaScriptu.

Dane LCP

PageSpeed Insights wyświetla do 4 różnych zbiorów danych CrUX:

  • Dane mobilne dla tego adresu URL
  • Danena komputeryTen URL
  • Mobilna transmisja danych dla całego obiektu Origin
  • Dane komputerów dla całego elementu Origin

Możesz je przełączać w elementach sterujących u góry i w prawym górnym rogu tej sekcji. Jeśli adres URL nie zawiera wystarczającej ilości danych do wyświetlenia na jego poziomie, ale zawiera dane na temat źródła, PageSpeed Insights zawsze pokazuje dane o źródle.

PageSpeed Insight powraca do danych na poziomie źródła, gdzie dane na poziomie adresu URL są niedostępne
Jeśli PageSpeed Insights nie ma danych na poziomie adresu URL, wyświetla dane na poziomie źródła.

LCP dla całego źródła może bardzo się różnić od LCP pojedynczej strony w zależności od tego, jak ten LCP jest wczytywany na tej stronie w porównaniu z innymi stronami w tym źródle. Może to również zależeć od sposobu, w jaki użytkownicy przechodzą na te strony. Strony główne są zwykle odwiedzane przez nowych użytkowników i dlatego często nie zawierają treści zapisanych w pamięci podręcznej, przez co są najwolniejsze.

Przyjrzyj się 4 różnym kategoriom danych raportu na temat użytkowania Chrome, aby zdecydować, czy problem LCP dotyczy konkretnej strony czy problemu w całej witrynie. Może też pokazywać, w przypadku których typów urządzeń występują problemy z LCP.

Dane dodatkowe

Deweloperzy pracujący nad optymalizacją LCP mogą też korzystać z czasów First Contentful Paint (FCP) i Time to First Byte (TTFB). Są to dobre dane diagnostyczne, które dostarczają cennych informacji o LCP.

TTFB to czas od rozpoczęcia otwierania strony (np. kliknięcia linku) przez użytkownika do momentu otrzymania pierwszych bajtów dokumentu HTML. Wysoki wskaźnik TTFB może sprawić, że uzyskanie 2,5-sekundowego LCP będzie trudne, a nawet niemożliwe.

Wysoka wartość TTFB może być spowodowana wieloma przekierowaniami serwerów, użytkownikami znajdującymi się daleko od najbliższego serwera witryny, użytkownikami o niskiej jakości połączenia sieciowego lub niemożnością użycia treści z pamięci podręcznej ze względu na parametry zapytań.

Gdy strona zacznie się renderować, może pojawić się pierwsze wyrenderowanie (np. kolor tła), a po nim trochę treści (np. nagłówek witryny). Wygląd początkowych treści jest mierzony przez FCP, a różnica między FCP a innymi danymi może być bardzo wyraźna.

Duża różnica między TTFB a FCP może oznaczać, że przeglądarka musi pobrać dużo zasobów blokujących renderowanie. Może to również oznaczać, że przeglądarka musi wykonać dużo pracy, aby wyrenderować istotne treści, co sugeruje, że witryna w dużym stopniu opiera się na renderowaniu po stronie klienta.

Duża różnica między FCP i LCP wskazuje, że przeglądarka nie ma od razu dostępu do zasobu LCP, aby określić priorytety (np. tekst lub obrazy są zarządzane przez JavaScript, a nie dostępne w początkowym kodzie HTML) albo że przeglądarka musi wykonać inne działania, aby wyświetlić zawartość LCP.

Używanie danych z PageSpeed Insights Lighthouse

Sekcja Lighthouse z PageSpeed Insights zawiera wskazówki dotyczące poprawy LCP, ale najpierw sprawdź, czy podany wskaźnik LCP jest ogólnie zgodny z rzeczywistymi danymi użytkowników dostarczonymi przez CrUX. Jeśli narzędzia Lighthouse i CrUX nie zgadzają się, ten raport prawdopodobnie uzyska dokładniejszy obraz wrażeń użytkowników. Zanim przystąpisz do działania, upewnij się, że dane raportu na temat użytkowania Chrome dotyczą Twojej strony, a nie pełnego źródła.

Jeśli narzędzia Lighthouse i CrUX podają wartości LCP, które wymagają poprawy, cenne wskazówki na temat poprawy LCP znajdziesz w sekcji dotyczącej tego narzędzia. Użyj filtra LCP, aby wyświetlić tylko kontrole dotyczące LCP:

Możliwości i diagnostyka LCP w LCP
Diagnostyka Lighthouse i sugestie dotyczące poprawy LCP.

Poza możliwościami, które warto poprawić, dostępne są też informacje diagnostyczne, które zawierają więcej informacji przydatnych podczas diagnozowania problemu. Diagnostyka największego wyrenderowania treści pokazuje przydatne zestawienie różnych czasów, które składają się na LCP:

Etapy LCP w LCP
Analiza elementów LCP w Lighthouse.

W następnej sekcji znajdziesz bardziej szczegółowe informacje o podkategoriach LCP.

Zestawienie LCP

W tej sekcji przedstawiamy metodologię podziału LCP na najważniejsze podkategorie, a także konkretne zalecenia i sprawdzone metody optymalizacji poszczególnych podkategorii.

Większość wczytywania stron obejmuje zwykle kilka żądań sieciowych, ale na potrzeby identyfikacji możliwości poprawy LCP zalecamy zacząć od wstępnego dokumentu HTML i ewentualnie z zasobu LCP.

Choć inne żądania na stronie mogą wpływać na LCP, te 2 żądania – w szczególności czas rozpoczęcia i zakończenia zasobu LCP – wskazują, czy strona jest zoptymalizowana pod kątem LCP.

Aby zidentyfikować zasób LCP, możesz użyć narzędzi dla programistów takich jak PageSpeed Insights, Chrome DevTools lub WebPageTest, aby określić element LCP. Z tego poziomu możesz dopasowywać adres URL (w stosownych przypadkach) wczytany przez element w kaskadzie sieci wszystkich zasobów wczytywanych przez stronę.

Na przykład ta wizualizacja przedstawia te zasoby wyróżnione na diagramie kaskady sieci podczas typowego wczytywania strony, gdzie element LCP wymaga żądania obrazu do wyrenderowania.

Kaskada sieci z wyróżnionymi zasobami HTML i LCP
Schemat kaskadowy pokazujący czasy wczytywania kodu HTML strony internetowej i zasoby potrzebne LCP.

W przypadku dobrze zoptymalizowanej strony żądanie zasobów LCP powinno rozpoczynać się jak najwcześniej, a element LCP powinien być renderowany tak szybko, jak to możliwe po zakończeniu ładowania zasobu LCP. Aby sprawdzić, czy dana strona jest zgodna z tą zasadą, możesz podzielić łączny czas LCP na te podkategorie:

Czas do pierwszego bajtu (TTFB)
Czas od rozpoczęcia wczytywania strony przez użytkownika do momentu, gdy przeglądarka otrzyma pierwszy bajt odpowiedzi dokumentu HTML.
Opóźnienie wczytywania zasobu
Czas między TTFB a rozpoczęciem ładowania zasobu LCP przez przeglądarkę. Jeśli do renderowania element LCP nie wymaga wczytania zasobów (np. jeśli element jest węzłem tekstowym renderowanym za pomocą czcionki systemowej), ten czas wynosi 0.
Czas wczytywania zasobu
Czas potrzebny na wczytanie zasobu LCP. Jeśli wyrenderowanie elementu LCP nie wymaga wczytania zasobu, ten czas wynosi 0.
Opóźnienie renderowania elementu
Czas między zakończeniem wczytywania zasobu LCP a pełnym wyrenderowaniem elementu LCP.

LCP każdej strony składa się z tych 4 podkategorii. Nie ma między nimi żadnych luk ani pokrywania się, łącząc się w pełny czas LCP.

Zestawienie LCP z uwzględnieniem 4 podkategorii
Ten sam diagram kaskadowy z nałożonymi na osi czasu 4 podkategoriami LCP.

Przy optymalizacji LCP warto zoptymalizować te podkategorie. Należy jednak zadbać o to, aby wszystkie były zoptymalizowane, ponieważ niektóre optymalizacje rozkładają zaoszczędzony czas z jednej strony na drugi, zamiast rzeczywiście go obniżać.

Na przykład w kaskadzie sieci zmniejszenie rozmiaru pliku obrazu przez jego dodatkową kompresję lub przełączenie na bardziej optymalny format (np. AVIF lub WebP) skróciłoby czas wczytywania zasobów, ale nie poprawi LCP, ponieważ ten czas staje się częścią opóźnienia renderowania elementu. Dzieje się tak, ponieważ element LCP jest ukryty, dopóki powiązany z nim JavaScript nie zostanie wczytany, po czym zostanie ujawniony.

Ten sam rozkład LCP przedstawiony wcześniej, gdzie podkategoria czasu wczytywania zasobów jest krótsza, ale ogólny czas LCP pozostaje bez zmian.
Skrócenie czasu wczytywania zasobu zwiększa opóźnienie renderowania elementu bez obniżania LCP.

Optymalne czasy podkategorii

Aby zoptymalizować poszczególne podkategorie LCP, trzeba wiedzieć, jaki jest idealny podział tych podkategorii na odpowiednio zoptymalizowanej stronie.

Należy maksymalnie ograniczyć te dwie podkategorie, które obejmują opóźnienia. Pozostałe 2 to żądania sieciowe, które z założenia potrzebują czasu i nie można ich całkowicie zoptymalizować.

Poniżej przedstawiono idealny rozkład LCP.

Podczęść LCP % LCP
Czas do pierwszego bajtu (TTFB) ok. 40%
Opóźnienie wczytywania zasobu <10%
Czas wczytywania zasobu ok. 40%
Opóźnienie renderowania elementu <10%
RAZEM 100%

Są to wytyczne, a nie ścisłe zasady. Jeśli wartości LCP Twoich stron utrzymują się konsekwentnie na poziomie 2,5 sekundy lub mniej, to, jak będzie wyglądał podział, nie ma znaczenia. Jeśli jednak kategorie opóźnień będą zbyt długie, możesz mieć problemy z osiągnięciem docelowej wartości 2,5 sekundy.

Zalecamy podejście do rozkładu czasu LCP w następujący sposób:

  • Większość czasu LCP musi zająć wczytywanie dokumentu HTML i źródła LCP.
  • Każdy okres przed LCP, w którym jeden z tych 2 zasobów się nie wczytuje, to okazja do ulepszenia.

Optymalizacja poszczególnych kategorii

Teraz gdy już wiesz, jak wyglądają podkategorie LCP na dobrze zoptymalizowanej stronie, możesz zacząć optymalizować swoje strony.

Sekcje poniżej zawierają rekomendacje i sprawdzone metody optymalizacji każdej kategorii, zaczynając od optymalizacji, które prawdopodobnie przyniosą największe korzyści.

Wyeliminuj opóźnienie wczytywania zasobów

Celem tego kroku jest jak najszybsze ładowanie zasobu LCP. Choć teoretycznie najwcześniejsze zasoby mogą się zacząć ładować zaraz po przekształceniu TTFB, w praktyce zawsze występuje pewne opóźnienie, zanim przeglądarki zaczną ładować zasoby.

Zalecamy, aby zasób LCP zaczynał się w tym samym czasie co pierwszy zasób, który wczytuje strona.

Diagram kaskady sieci przedstawiającej zasób LCP, począwszy od pierwszego zasobu, co wskazuje możliwość poprawy
Na tej stronie zasób LCP zaczyna się wczytywać dobrze po arkuszu stylów, który wczytuje się jako pierwszy. Można tu coś poprawić.

Ogólnie na szybkość ładowania zasobu LCP wpływają 2 czynniki:

  • Kiedy zasób zostanie odkryty.
  • Priorytet ma przypisany zasób.

Optymalizacja po wykryciu zasobu

Aby zasób LCP zaczął ładować się jak najszybciej, musi on być wykrywalny w początkowej odpowiedzi dokumentu HTML przez skaner wstępnego wczytywania przeglądarki. Oto kilka przykładów wykrywalnych zasobów LCP:

  • Element <img>, którego atrybuty src lub srcset znajdują się we początkowych znacznikach HTML.
  • Każdy element, który wymaga obrazu tła CSS, jeśli ten obraz został wstępnie wczytany przez atrybut <link rel="preload"> w znacznikach HTML (lub za pomocą nagłówka Link).
  • Węzeł tekstowy, który do renderowania wymaga czcionki internetowej, o ile czcionka jest wstępnie wczytywana przez atrybut <link rel="preload"> w znacznikach HTML (lub za pomocą nagłówka Link).

Oto niektóre zasoby LCP, których nie można wykryć, skanując odpowiedź dokumentu HTML. W każdym przypadku przeglądarka musi uruchomić skrypt lub zastosować arkusz stylów, aby wykryć i rozpocząć wczytywanie zasobu LCP, co będzie wymagało oczekiwania na zakończenie żądań sieciowych.

  • Element <img> dodawany do strony dynamicznie za pomocą JavaScriptu.
  • Każdy element leniwie ładowany za pomocą biblioteki JavaScript, która ukrywa atrybuty src lub srcset (często jako data-src lub data-srcset).
  • Każdy element, który wymaga obrazu tła CSS.

Aby wyeliminować niepotrzebne opóźnienie wczytywania zasobów, zasób LCP musi być wykrywalny w źródle HTML. Jeśli do zasobu odwołuje się tylko zewnętrzny plik CSS lub JavaScript, zasób LCP musi być wstępnie wczytany z wysokim priorytetem pobierania, np.:

<!-- Load the stylesheet that will reference the LCP image. -->
<link rel="stylesheet" href="/path/to/styles.css">

<!-- Preload the LCP image with a high fetchpriority so it starts loading with the stylesheet. -->
<link rel="preload" fetchpriority="high" as="image" href="/path/to/hero-image.webp" type="image/webp">

Optymalizacja priorytetu przyznawanego zasobowi

Nawet jeśli zasób LCP jest wykrywalny w znacznikach HTML, wciąż może zacząć się ładować dopiero od pierwszego zasobu. Może się tak zdarzyć, jeśli ustawienia heurystyki priorytetowej skanera w przeglądarce nie rozpoznają, że zasób jest ważny, lub jeśli uzna, że inne zasoby są ważniejsze.

Możesz np. opóźnić wyświetlanie obrazu LCP za pomocą kodu HTML, jeśli w elemencie <img> ustawisz loading="lazy". Korzystanie z leniwego ładowania oznacza, że zasób nie będzie wczytywany, dopóki układ nie potwierdzi, że znajduje się on w widocznym obszarze, co często powoduje późniejsze załadowanie.

Nawet bez leniwego ładowania przeglądarki nie ładują początkowo obrazów o wysokim priorytecie, ponieważ nie blokują one renderowania. Priorytet wczytywania zasobu możesz zwiększyć za pomocą atrybutu fetchpriority w ten sposób:

<img fetchpriority="high" src="/path/to/hero-image.webp">

Warto ustawić fetchpriority="high" w elemencie <img>, jeśli uważasz, że może to być element LCP Twojej strony. Jednak ustawienie wysokiego priorytetu więcej niż 1 lub 2 obrazom sprawia, że ustawienie priorytetu nie pomaga w zmniejszaniu LCP.

Możesz też obniżyć priorytet obrazów, które mogą pojawiać się na początku odpowiedzi dokumentu, ale są niewidoczne ze względu na styl, na przykład obrazy na slajdach karuzeli, które nie są widoczne podczas uruchamiania:

<img fetchpriority="low" src="/path/to/carousel-slide-3.webp">

Zmniejszenie priorytetu niektórych zasobów może zwiększyć przepustowość dla zasobów, które ich potrzebują, ale uważaj, żeby nie przesadzić. Zawsze sprawdzaj priorytet zasobów w Narzędziach deweloperskich i testuj zmiany za pomocą modułów i narzędzi terenowych.

Po zoptymalizowaniu priorytetu zasobów LCP i czasu ich wykrywania Twoja kaskada sieci powinna wyglądać tak (zasób LCP zaczyna się w tym samym czasie co pierwszy zasób):

Diagram kaskady sieci przedstawiający zasób LCP, który rozpoczyna się w tym samym czasie co pierwszy zasób
Zasób LCP zacznie się teraz ładować w tym samym czasie co arkusz stylów.

Co ważne, zasób LCP może nie zacząć ładować się tak szybko, nawet jeśli jest wykrywalny ze źródła HTML. Dzieje się tak dlatego, że znajduje się w innym źródle, z którym przeglądarka musi się połączyć, aby mogła rozpocząć ładowanie zasobu. Zalecamy hostowanie w miarę możliwości zasobów krytycznych w tym samym źródle co zasób dokumentu HTML, tak aby przeglądarka mogła ponownie wykorzystać istniejące połączenie i zaoszczędzić czas (więcej na ten temat później).

Eliminowanie opóźnienia renderowania elementu

Celem tego kroku jest zapewnienie możliwości wyrenderowania elementu LCP natychmiast po zakończeniu wczytywania jego zasobu, niezależnie od tego, kiedy to nastąpi.

Głównym powodem, dla którego element LCP nie może wyrenderować się od razu po zakończeniu ładowania zasobu, jest zablokowanie renderowania z innego powodu:

  • Renderowanie całej strony jest zablokowane z powodu arkuszy stylów lub synchronicznych skryptów w komponencie <head>, które wciąż się ładują.
  • Zasób LCP został wczytany, ale element LCP nie został jeszcze dodany do modelu DOM, ponieważ oczekuje na wczytanie kodu JavaScript.
  • Element jest ukryty przez inny kod, np. przez bibliotekę testów A/B, która nie określiła jeszcze, do której grupy eksperymentalnej należy umieścić użytkownika.
  • Wątek główny jest zablokowany z powodu długich zadań, a renderowanie musi czekać na ich zakończenie.

Poniżej opisujemy, jak rozwiązać najczęstsze przyczyny zbędnego opóźnienia renderowania elementów.

Ogranicz lub wbudowaj arkusze stylów blokujące renderowanie

Arkusze stylów są wczytywane z bloku znaczników HTML podczas renderowania całej otaczającej je treści. Jest to zwykle korzystne, ponieważ umożliwia zastosowanie arkusza stylów przed wczytaniem innych elementów. Jeśli jednak arkusz stylów jest tak duży, że wczytywanie trwa znacznie dłużej niż w przypadku zasobu LCP, uniemożliwia on renderowanie elementu LCP nawet po zakończeniu ładowania zasobu, jak widać w tym przykładzie:

Diagram kaskady sieci przedstawiającej duży plik CSS blokujący renderowanie elementu LCP, ponieważ wczytywanie trwa dłużej niż zasób LCP
W tym samym czasie zaczynają się ładować obraz i arkusz stylów, ale renderowanie obrazu nie jest możliwe, dopóki arkusz stylów nie będzie gotowy.

Aby rozwiązać ten problem, wykonaj jedną z tych czynności:

  • wbudować arkusz stylów w kod HTML, aby uniknąć dodatkowego żądania sieciowego;
  • zmniejsz rozmiar arkusza stylów.

Wbudowanie arkusza stylów działa tylko w przypadku zmniejszenia LCP tylko wtedy, gdy jest on mały. Jeśli jednak wczytanie arkusza stylów trwa dłużej niż zasób LCP, jest on prawdopodobnie za duży, aby można było skutecznie go wstawić. W takiej sytuacji zalecamy zmniejszenie złożoności arkusza stylów w ten sposób:

Opóźnij lub wstaw kod JavaScript blokujący renderowanie

Zalecamy asynchroniczne korzystanie ze wszystkich skryptów na stronach za pomocą atrybutów async lub defer. Stosowanie skryptów synchronicznych prawie zawsze obniża wydajność.

Jeśli jednak masz JavaScript, który musi uruchamiać się jak najwcześniej podczas wczytywania strony, możesz poprawić LCP, wbudowując małe skrypty w celu skrócenia czasu oczekiwania przeglądarki na żądania sieciowe.

Tak
<head>
  <script>
    // Inline script contents directly in the HTML.
    // IMPORTANT: only do this for very small scripts.
  </script>
</head>
Nie
<head>
  <script src="/path/to/main.js"></script>
</head>

Używaj renderowania po stronie serwera

Renderowanie po stronie serwera (SSR) to proces uruchamiania logiki aplikacji po stronie klienta na serwerze i odpowiadania na żądania dokumentów HTML przy użyciu pełnych znaczników HTML.

SSR pomaga w optymalizacji LCP w następujący sposób:

  • Sprawia, że Twoje zasoby są wykrywalne w źródle HTML, jak omówiliśmy w sekcji Eliminowanie opóźnienia wczytywania zasobów.
  • Dzięki temu nie trzeba będzie wykonywać dodatkowych żądań JavaScript, zanim strona zostanie wyrenderowana.

Główną wadą SSR jest to, że wymaga dodatkowego czasu przetwarzania serwera, co może spowolnić przetwarzanie TTFB. Zazwyczaj warto jednak liczyć na ten kompromis, ponieważ możesz mieć wpływ na czas przetwarzania serwera, podczas gdy możliwości sieci i urządzeń użytkowników – nie.

Aby zwiększyć wydajność, zalecamy też generowanie stron HTML na etapie kompilacji, a nie na żądanie. Nazywa się to statycznym generowaniem witryn (SSG) lub wstępnym renderowaniem.

Rozkładanie długich zadań

Nawet jeśli wykonasz wszystkie te wskazówki, a Twój kod JavaScript nie blokuje renderowania ani nie odpowiada za renderowanie elementów, wciąż może opóźniać LCP.

Najczęstszą przyczyną jest to, że gdy strona wczytuje duży plik JavaScript, potrzeba czasu na analizę i wykonywanie kodu przez przeglądarkę w wątku głównym. Oznacza to, że nawet jeśli zasób LCP zostanie w pełni pobrany, może on nadal czekać na wyrenderowanie, aż niepowiązany skrypt zostanie wykonany.

Wszystkie przeglądarki renderują obrazy w wątku głównym, co oznacza, że blokowanie go może też spowodować niepotrzebne opóźnienie renderowania elementu. Dlatego zalecamy podział dużego pliku JavaScript na kilka plików skryptów, które można w razie potrzeby analizować.

Skrócenie czasu wczytywania zasobów

Ten krok ma na celu skrócenie czasu potrzebnego przez przeglądarkę na przesyłanie zasobu przez sieć na urządzenie użytkownika. Można to zrobić na kilka sposobów:

  • Zmniejsz rozmiar zasobu.
  • Zmniejsz odległość, jaką musi pokonać zasób.
  • Zmniejszenie rywalizacji o przepustowość sieci.
  • Wyeliminuj czas pracy sieci.

Zmniejsz rozmiar zasobu

Zasoby LCP to zwykle obrazy lub czcionki internetowe. Szczegółowe informacje o zmniejszaniu rozmiaru obu formatów znajdziesz w tych przewodnikach:

Zmniejsz odległość, jaką musi pokonać zasób

Możesz też skrócić czas ładowania, znajdując swoje serwery możliwie najbliżej użytkowników. Najlepszym sposobem, aby to zrobić, jest skorzystanie z sieci dostarczania treści (CDN).

Szczególnie przydatne są sieci CDN dotyczące obrazów, ponieważ zmniejszają one odległość, jaką musi pokonać zasób, i często zmniejszają jego rozmiar zgodnie z przedstawionymi wcześniej strategiami.

Co ważne, sieci CDN z obrazami to świetny sposób na skrócenie czasu wczytywania zasobów. Hostowanie obrazów w domenie zewnętrznej wiąże się jednak z dodatkowymi kosztami połączenia. Wstępne łączenie ze źródłem może zmniejszyć niektóre koszty, ale najlepszym rozwiązaniem jest wyświetlanie obrazów z tego samego źródła co dokument HTML. Aby to umożliwić, wiele sieci CDN pozwala na wysyłanie żądań ze swojego punktu początkowego do ich serwerów proxy.

Zmniejszenie rywalizacji o przepustowość sieci

Jeśli strona wczytuje wiele zasobów jednocześnie, ładowanie każdego z nich może zająć dużo czasu. Ten problem jest znany jako rywalizacja z siecią.

Jeśli zasób LCP ma wysoki wskaźnik fetchpriority i jak najszybciej zaczniesz go ładować, przeglądarka robi wszystko, co może, aby zasoby o niższym priorytecie nie konkurowały z nim. Jednak ładowanie zbyt wielu zasobów jednocześnie może nadal wpływać na LCP, zwłaszcza jeśli wiele z nich ma wysoką wartość fetchpriority. Zalecamy ograniczenie rywalizacji o sieć, upewniając się, że jedyne zasoby o dużej wartości fetchpriority to te, które muszą wczytywać się najszybciej.

Całkowicie wyeliminuj czas pracy sieci

Najlepszym sposobem na skrócenie czasu wczytywania zasobów jest całkowite wyeliminowanie sieci z tego procesu. Jeśli udostępniasz swoje zasoby za pomocą efektywnej zasady kontroli pamięci podręcznej, użytkownicy, którzy zażądają tych zasobów po raz drugi, będą udostępniały je z pamięci podręcznej, co pozwoli skrócić czas wczytywania zasobów do zera.

Jeśli zasobem LCP jest czcionka internetowa, oprócz zmniejszenia rozmiaru czcionki internetowej zalecamy też rozważenie, czy musisz blokować renderowanie przy wczytywaniu tego zasobu. Jeśli ustawisz wartość font-display inną niż auto lub block, tekst będzie zawsze widoczny podczas wczytywania, a LCP nie będzie musiało czekać na dodatkowe żądanie sieciowe.

Jeśli zasób LCP jest mały, warto umieścić je w tekście jako identyfikator URI danych, aby wyeliminować dodatkowe żądania sieciowe. Korzystanie z identyfikatorów URI danych ma jednak swoje wady: zapobiega buforowaniu zasobów, a w niektórych przypadkach może powodować dłuższe opóźnienia renderowania ze względu na dodatkowe koszty dekodowania.

4. Skróć czas do pierwszego bajtu

Ten etap ma na celu jak najszybsze przesłanie początkowego HTML. Ten krok jest wymieniony na końcu, ponieważ zwykle to deweloperzy mają nad tym najmniejszą kontrolę. Jest to jednak również jeden z najważniejszych kroków, ponieważ bezpośrednio wpływa na każdy kolejny krok. Nic nie nastąpi w frontendzie, dopóki backend nie dostarczy pierwszego bajtu treści, więc wszystko, co możesz zrobić, aby przyspieszyć przetwarzanie TTFB, poprawi też wszystkie pozostałe dane o obciążeniu.

Częstą przyczyną powolnego zamiany tekstu na mowę w przypadku witryny o innej szybkości jest odsyłanie użytkowników za pomocą wielu przekierowań, np. przez reklamy lub skrócone linki. Zawsze ogranicz liczbę przekierowań, które musi czekać użytkownik.

Inną częstą przyczyną jest brak możliwości korzystania z pamięci podręcznej z serwera brzegowego CDN, przez co wszystkie żądania muszą być kierowane z powrotem na serwer pierwotny. Może się tak zdarzyć, jeśli użytkownicy korzystają z unikalnych parametrów adresu URL w celach analitycznych, nawet jeśli nie prowadzą do różnych stron.

Szczegółowe wskazówki dotyczące ograniczania liczby TTFB znajdziesz w artykule Optimize TTFB.

Monitorowanie rozkładu LCP w JavaScript

Informacje o czasie we wszystkich podkategoriach LCP są dostępne w języku JavaScript za pomocą kombinacji następujących interfejsów API wydajności:

Obliczenie tych wartości czasu w języku JavaScript pozwala wysłać je do dostawcy usług analitycznych lub rejestrować w narzędziach dla programistów, aby ułatwić debugowanie i optymalizację. Na przykład ten zrzut ekranu wykorzystuje metodę performance.measure() z interfejsu User Timing API, by dodać słupki do ścieżki czasu w panelu wydajności Narzędzi deweloperskich w Chrome:

Wskaźniki czasu działań użytkownika w podkategoriach LCP wizualizowanych w Narzędziach deweloperskich w Chrome
Ścieżka Czasów zawiera ramy czasowe dla podkategorii LCP.

Wizualizacje na ścieżce Czasy są szczególnie przydatne obok ścieżek Sieć i Wątek główny, które pozwalają sprawdzić, co jeszcze dzieje się na stronie w tych okresach.

Możesz też użyć JavaScriptu, aby obliczyć, jaki procent łącznego czasu LCP zajmuje każda podkategoria, i określić, czy Twoje strony spełniają zalecane zestawienia procentowe.

Ten zrzut ekranu pokazuje przykład, który rejestruje w konsoli łączny czas każdej podkategorii LCP, a także jej odsetek łącznego czasu LCP.

Czas podkategorii LCP oraz ich procentowy udział w LCP są wyświetlane w konsoli.
Czasy i odsetki podkategorii LCP.

Obie te wizualizacje zostały utworzone za pomocą tego kodu:

const LCP_SUB_PARTS = [
  'Time to first byte',
  'Resource load delay',
  'Resource load time',
  'Element render delay',
];

new PerformanceObserver((list) => {
  const lcpEntry = list.getEntries().at(-1);
  const navEntry = performance.getEntriesByType('navigation')[0];
  const lcpResEntry = performance
    .getEntriesByType('resource')
    .filter((e) => e.name === lcpEntry.url)[0];

  // Ignore LCP entries that aren't images to reduce DevTools noise.
  // Comment this line out if you want to include text entries.
  if (!lcpEntry.url) return;

  // Compute the start and end times of each LCP sub-part.
  // WARNING! If your LCP resource is loaded cross-origin, make sure to add
  // the `Timing-Allow-Origin` (TAO) header to get the most accurate results.
  const ttfb = navEntry.responseStart;
  const lcpRequestStart = Math.max(
    ttfb,
    // Prefer `requestStart` (if TOA is set), otherwise use `startTime`.
    lcpResEntry ? lcpResEntry.requestStart || lcpResEntry.startTime : 0
  );
  const lcpResponseEnd = Math.max(
    lcpRequestStart,
    lcpResEntry ? lcpResEntry.responseEnd : 0
  );
  const lcpRenderTime = Math.max(
    lcpResponseEnd,
    // Use LCP startTime (the final LCP time) because there are sometimes
    // slight differences between loadTime/renderTime and startTime
    // due to rounding precision.
    lcpEntry ? lcpEntry.startTime : 0
  );

  // Clear previous measures before making new ones.
  // Note: due to a bug, this doesn't work in Chrome DevTools.
  LCP_SUB_PARTS.forEach((part) => performance.clearMeasures(part));

  // Create measures for each LCP sub-part for easier
  // visualization in the Chrome DevTools Performance panel.
  const lcpSubPartMeasures = [
    performance.measure(LCP_SUB_PARTS[0], {
      start: 0,
      end: ttfb,
    }),
    performance.measure(LCP_SUB_PARTS[1], {
      start: ttfb,
      end: lcpRequestStart,
    }),
    performance.measure(LCP_SUB_PARTS[2], {
      start: lcpRequestStart,
      end: lcpResponseEnd,
    }),
    performance.measure(LCP_SUB_PARTS[3], {
      start: lcpResponseEnd,
      end: lcpRenderTime,
    }),
  ];

  // Log helpful debug information to the console.
  console.log('LCP value: ', lcpRenderTime);
  console.log('LCP element: ', lcpEntry.element, lcpEntry.url);
  console.table(
    lcpSubPartMeasures.map((measure) => ({
      'LCP sub-part': measure.name,
      'Time (ms)': measure.duration,
      '% of LCP': `${
        Math.round((1000 * measure.duration) / lcpRenderTime) / 10
      }%`,
    }))
  );
}).observe({type: 'largest-contentful-paint', buffered: true});

Możesz użyć tego kodu w niezmienionej postaci do lokalnego debugowania lub zmodyfikować go, aby wysyłać dane do dostawcy usług analitycznych, co pozwoli Ci lepiej zrozumieć, jak rozkład LCP Twoich stron dotyczy rzeczywistych użytkowników.

Sprawdzaj rozkład LCP za pomocą rozszerzenia wskaźników internetowych

Rozszerzenie Web Vitals rejestruje czas LCP, element LCP i 4 podkategorie w logowaniu konsoli, aby pokazać to zestawienie.

Zrzut ekranu z logowaniem w konsoli rozszerzenia Wskaźniki internetowe pokazujące czasy poszczególnych części LCP
Panel Konsola dotyczący rozszerzenia Wskaźniki internetowe pokazuje zestawienie LCP.