Optymalizacja największego wyrenderowania treści

Szczegółowy przewodnik wyjaśniający, jak obniżyć wartość LCP i zidentyfikować obszary wymagające poprawy.

Największe wyrenderowanie treści (LCP) to jeden z 3 podstawowych wskaźników internetowych. Przedstawia, jak szybko wczytuje się główna treść strony internetowej. W szczególności LCP mierzy 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, wskaźnik LCP powinien wynosić maksymalnie 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 mieć wpływ wiele czynników, a opóźnienia w każdym z nich mogą mieć znaczący wpływ na LCP.

Rzadko się zdarza, by szybka poprawka w jednej części strony mogła znacząco poprawić wskaźnik 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 powinni sprawdzić, czy w ogóle występuje problem LCP i jaki jest jego zakres.

LCP można mierzyć za pomocą różnych narzędzi i nie wszystkie pomiary są mierzone w taki sam sposób. Aby poznać wskaźnik LCP prawdziwych użytkowników, skupmy się na wrażeniach rzeczywistych użytkowników, a nie na tym, co pokazuje narzędzie laboratoryjne, takie jak Lighthouse czy testy lokalne. Te laboratoryjne narzędzia mogą dostarczyć wielu informacji do wyjaśnienia i poprawienia LCP. Pamiętaj jednak, że same testy laboratoryjne mogą nie odzwierciedlać dokładnie rzeczywistych wrażeń użytkowników.

Dane LCP oparte na prawdziwych użytkownikach można uzyskać 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.

Korzystanie z danych LCP PageSpeed Insights CrUX

Narzędzie PageSpeed Insights zapewnia dostęp do danych raportu na temat użytkowania Chrome w górnej sekcji zatytułowanej Poznaj wrażenia użytkowników. Bardziej szczegółowe dane laboratoryjne są dostępne w dolnej sekcji zatytułowanej Diagnozuj problemy z wydajnością. Jeśli w przypadku Twojej witryny dostępne są dane raportu na temat użytkowania Chrome, zawsze skoncentruj się najpierw na rzeczywistych danych użytkownika.

Dane raportu na temat użytkowania Chrome wyświetlane w PageSpeed Insights
Dane dotyczące użytkowania Chrome zostały wyświetlone w PageSpeed Insights.

PageSpeed Insights wyświetla maksymalnie 4 różne dane na temat użytkowania Chrome:

  • 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ć za pomocą elementów 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 ma 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 znacznie 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, więc często są wczytywane „na zimno” bez zawartości pamięci podręcznej. Często są to najwolniejsze strony w witrynie.

Aby określić, czy problem LCP dotyczy tylko tej strony, czy problemu w całej witrynie, zapoznaj się z 4 różnymi kategoriami danych raportu na temat użytkowania Chrome. Może też pokazywać, w przypadku których typów urządzeń występują problemy z LCP.

Korzystanie z dodatkowych danych PageSpeed Insights CrUX

Jeśli chcesz zoptymalizować LCP, skorzystaj z etapów czasowych pierwszego wyrenderowania treści (FCP) i czasu do pierwszego bajtu (TTFB) – są to dobre dane diagnostyczne, które mogą dostarczyć cennych informacji o LCP.

TTFB oznacza czas, od którego użytkownik rozpoczyna przechodzenie na stronę (np. klika link) do momentu otrzymania pierwszych bajtów dokumentu HTML. Wysoki wskaźnik TTFB może sprawić, że uzyskanie 2,5-sekundowego LCP będzie wyzwaniem, 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 z powodu parametrów 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 przy użyciu FCP. Różnica między FCP a innymi wskaźnikami 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 musi wykonać dużo pracy, aby wyrenderować jakąkolwiek istotną treść – to klasyczny znak witryny, w której w dużym stopniu opiera się renderowanie po stronie klienta.

Duża różnica między FCP i LCP oznacza, że zasób LCP nie jest od razu dostępny dla przeglądarki, aby nadać priorytet (np. tekst lub obrazy są zarządzane przez JavaScript, a nie dostępne w początkowym kodzie HTML) albo że przeglądarka wykonuje inne działania, zanim będzie mogła wyświetlić zawartość LCP.

Korzystanie z danych PageSpeed Insights Lighthouse

Sekcja Lighthouse z PageSpeed Insights zawiera wskazówki dotyczące poprawy LCP, ale najpierw sprawdź, czy podany wskaźnik LCP jest w dużym stopniu 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, sekcja poświęcona Lighthouse może zawierać cenne wskazówki na temat sposobów zwiększania LCP. Użyj filtra LCP, aby wyświetlić tylko kontrole dotyczące LCP:

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

Poza możliwościami, które warto wprowadzić, 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
Zestawienie elementów LCP w LCP.

Zajmiemy się nimi w następnej kolejności.

Zestawienie LCP

Optymalizacja LCP może być bardziej skomplikowanym zadaniem, gdy PageSpeed Insights nie pokaże Ci, jak poprawić ten wskaźnik. W przypadku złożonych zadań lepiej jest podzielić je na mniejsze, łatwiejsze do wykonania zadania i zająć się nimi oddzielnie.

W tej sekcji przedstawiamy metodologię podziału LCP na najważniejsze części, a następnie konkretne zalecenia i sprawdzone metody optymalizacji poszczególnych elementów.

Większość wczytań stron obejmuje zwykle wiele żądań sieciowych, ale aby zidentyfikować możliwości poprawy LCP, warto zacząć od 2 analiz:

  1. Początkowy dokument HTML
  2. Zasób LCP (jeśli dotyczy)

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 omówione powyżej statystyki PageSpeed Insights, Chrome DevTools czy WebPageTest) w celu określenia elementu LCP. Z tego poziomu możesz dopasować adres URL (ponownie, jeśli dotyczy) 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
Diagram 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 konkretna strona jest zgodna z tą zasadą, możesz podzielić łączny czas LCP na następujące podczęści:

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 element LCP nie wymaga do renderowania wczytania zasobów, 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.

Wartość LCP każdej strony można podzielić na 4 podczęści. Nie ma między nimi żadnych rozbieżności. Łącznie dają one pełny czas LCP.

Przy optymalizacji LCP warto spróbować zoptymalizować poszczególne podczęści. Trzeba jednak pamiętać, że trzeba je zoptymalizować. W niektórych przypadkach optymalizacja zastosowana w jednej części nie poprawi LCP, a jedynie przesunąć zaoszczędzony czas w inny sposób.

Na przykład w wcześniejszej kaskadzie sieci zmniejszenie rozmiaru pliku przez jego skompresowanie lub przez przełączenie na bardziej optymalny format (takiego jak AVIF lub WebP) skróciłoby czas ładowania zasobu, ale nie poprawiłby LCP, ponieważ czas przesunąłby się do części dotyczącej opóźnienia renderowania elementu:

Taki sam podział LCP przedstawiony wcześniej, gdy 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.

Dzieje się tak, ponieważ na tej stronie element LCP jest ukryty, dopóki kod JavaScript nie zostanie wczytany, a wszystko zostanie ujawnione za jednym razem.

Ten przykład ilustruje, dlaczego należy zoptymalizować wszystkie te podczęści, aby uzyskać najlepsze wyniki LCP.

Optymalne przedziały czasowe

W celu optymalizacji poszczególnych części LCP należy wiedzieć, jaki jest idealny podział tych podczęści na dobrze zoptymalizowaną stronę.

Dwie z czterech podczęści mają w nazwie słowo „opóźnienie”. To wskazówka, że chcesz, aby te czasy były jak najbliżej zera. Pozostałe 2 części to żądania sieciowe, które z natury wymagają czasu.

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

Pamiętaj, że podane tu przedziały czasowe są wytycznymi, a nie ścisłymi zasadami. Jeśli wartość LCP na Twoich stronach utrzymuje się konsekwentnie w zakresie 2,5 sekundy, ich proporcje nie mają znaczenia. Jeśli jednak spędzasz zbyt dużo czasu w każdej z tych „opóźnień”, bardzo trudno będzie stale osiągać cel wynoszący 2,5 sekundy.

Oto dobry sposób na analizę czasu LCP:

  • Zdecydowaną większość czasu LCP powinno zająć wczytywanie dokumentu HTML i źródła LCP.
  • Każdy okres przed LCP, w którym jeden z tych 2 zasobów nie wczytuje się, jest szansa na ulepszenie.

Jak zoptymalizować poszczególne elementy

Skoro już wiesz, jak rozkładają się poszczególne części składowe LCP na dobrze zoptymalizowanej stronie, możesz przystąpić do optymalizacji własnych stron.

W kolejnych 4 częściach znajdziesz rekomendacje i sprawdzone metody optymalizacji każdej z nich. Są one przedstawione po kolei, zaczynając od optymalizacji, które najprawdopodobniej przyniosą największe korzyści.

1. Wyeliminuj opóźnienie wczytywania zasobów.

Celem tego kroku jest jak najszybsze ładowanie zasobu LCP. Teoretycznie najwcześniejszy zasób może zacząć się ładować zaraz po przekształceniu TTFB, ale w praktyce zawsze następuje opóźnienie przed rozpoczęciem ładowania zasobów przez przeglądarki.

Jako zasadę możesz przyjąć, że ładowanie zasobu LCP powinno nastąpić w tym samym czasie co pierwszy zasób wczytywany przez tę stronę. Inaczej mówiąc, jeśli zasób LCP zacznie ładować się później niż pierwszy, będzie to oznaczało możliwości wprowadzenia ulepszeń.

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 ładować się długo 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, ważne jest, by był on wykrywalny we wstępnej odpowiedzi dokumentu HTML przez skaner wstępnego wczytywania przeglądarki. W poniższych przypadkach przeglądarka może na przykład wykryć zasób LCP, skanując odpowiedź dokumentu HTML:

  • Element LCP jest elementem <img>, a jego atrybuty src lub srcset znajdują się we początkowych znacznikach HTML.
  • Element LCP wymaga obrazu tła CSS, ale ten obraz jest wstępnie wczytywany za pomocą <link rel="preload"> w znacznikach HTML (lub za pomocą nagłówka Link).
  • Element LCP to węzeł tekstowy, który do renderowania wymaga czcionki internetowej, która jest wczytywana za pomocą <link rel="preload"> w znacznikach HTML (lub za pomocą nagłówka Link).

Oto kilka przykładów sytuacji, w których zasobu LCP nie można wykryć podczas skanowania odpowiedzi dokumentu HTML:

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

W każdym z tych przypadków przeglądarka musi uruchomić skrypt lub zastosować arkusz stylów, co zwykle wiąże się z oczekiwaniem na zakończenie żądań sieciowych – zanim będzie mogła wykryć zasób LCP i zacząć go ładować. Ta metoda nigdy nie jest optymalna.

Aby uniknąć zbędnego opóźnienia wczytywania zasobów, zasób LCP powinien być wykrywalny w źródle HTML. Jeśli do zasobu odwołuje się tylko zewnętrzny plik CSS lub JavaScript, zasób LCP powinien 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 na przykład 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 obraz znajduje się w widocznym obszarze. Ładowanie może rozpocząć się później niż w przeciwnym razie.

Nawet bez leniwego ładowania obrazy nie są początkowo wczytywane z najwyższym priorytetem, ponieważ nie są zasobami blokującymi renderowanie. Korzystając z atrybutu fetchpriority, możesz wskazać przeglądarkom, które zasoby są najważniejsze, jeśli ich priorytet może być wyższy:

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

Zalecamy ustawienie atrybutu 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 nie są widoczne 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 zmniejszyć obciążenie dla zasobów, które potrzebują go więcej. Zachowaj jednak ostrożność. Zawsze sprawdzaj priorytet zasobów w Narzędziach deweloperskich i testuj zmiany za pomocą modułów i narzędzi funkcjonalnych.

Po zoptymalizowaniu priorytetu zasobów LCP i czasu 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.

2. Wyeliminuj opóźnienie 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 zostać wyrenderowany natychmiast po zakończeniu wczytywania 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 są nadal wczytywane.
  • Zasób LCP zakończył się, ale element LCP nie został jeszcze dodany do modelu DOM (oczekuje na wczytanie kodu JavaScript).
  • Element jest ukrywany przez inny kod, np. przez bibliotekę testów A/B, która nadal określa eksperyment, w którym powinien uczestniczyć użytkownik.
  • 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ących renderowanie

Arkusze stylów wczytywane ze znaczników HTML blokują renderowanie całej następującej po nich treści. Jest to korzystne, ponieważ zazwyczaj nie należy renderować kodu HTML bez stylu. Jeśli jednak arkusz stylów jest tak duży, że wczyta się znacznie dłużej niż zasób LCP, uniemożliwi renderowanie elementu LCP nawet po zakończeniu ładowania zasobu, jak pokazano 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.

Ogólnie rzecz biorąc, wbudowanie arkusza stylów jest zalecane tylko wtedy, gdy jest on mały, bo treść wbudowana w kodzie HTML nie może korzystać z buforowania przy kolejnych wczytaniach stron. Jeśli arkusz stylów jest tak duży, że trwa dłużej niż wczytanie zasobu LCP, raczej nie będzie on odpowiednim kandydatem do wbudowania.

W większości przypadków najlepszym sposobem, aby arkusz stylów nie blokował renderowania elementu LCP, jest zmniejszenie jego rozmiaru, tak aby był on mniejszy niż zasób LCP. Dzięki temu w przypadku większości wizyt nie będzie to wąskie gardło.

Oto kilka zaleceń dotyczących zmniejszenia rozmiaru arkusza stylów:

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

Prawie nigdy nie ma potrzeby dodawania skryptów synchronicznych (skryptów bez atrybutów async lub defer) do <head> stron, bo prawie zawsze ma to negatywny wpływ na wydajność.

Jeśli kod JavaScript musi zostać uruchomiony jak najwcześniej podczas wczytywania strony, najlepiej jest umieścić go w tekście, aby renderowanie nie opóźniło oczekiwania na kolejne żądanie sieciowe. Podobnie jak w przypadku arkuszy stylów, skrypty wbudowane należy stosować tylko wtedy, gdy są bardzo małe.

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

Z perspektywy optymalizacji LCP należy wyróżnić 2 główne zalety SSR:

  • Zasoby graficzne będzie można znaleźć w źródle HTML (co zostało omówione w kroku 1 wcześniej).
  • Wyrenderowanie zawartości strony nie będzie wymagać dodatkowych żądań JavaScript do zakończenia jej wyświetlania.

Główną wadą SSR jest to, że wymaga dodatkowego czasu przetwarzania serwera, co może spowolnić przetwarzanie TTFB. Jest to jednak zwykle warte kontroli, ponieważ to Ty masz kontrolę nad czasem przetwarzania serwera, podczas gdy możliwości sieciowe i urządzenia użytkowników – nie.

Podobna opcja do SSR nosi nazwę statycznego generowania witryn (SSG) lub wstępnego renderowania. polega na generowaniu stron HTML na etapie kompilacji, a nie na żądanie. Jeśli Twoja architektura umożliwia renderowanie wstępne, zwykle jest to lepsze rozwiązanie ze względu na wydajność.

Rozkładanie długich zadań

Nawet jeśli zastosujesz się do wcześniejszych wskazówek, 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 wczytywanie dużych plików JavaScript, które muszą zostać przeanalizowane i wykonane w głównym wątku przeglądarki. Oznacza to, że nawet jeśli zasób graficzny zostanie w całości pobrany, przed wyrenderowaniem może być konieczne czekanie na zakończenie wykonywania niepowiązanego skryptu.

Wszystkie przeglądarki renderują obecnie obrazy w wątku głównym, co oznacza, że wszystko, co blokuje wątek główny, może też prowadzić do niepotrzebnego opóźnienia renderowania elementu.

3. Skrócenie czasu wczytywania zasobu

Ten krok ma na celu skrócenie czasu potrzebnego na przesyłanie bajtów zasobu przez sieć na urządzenie użytkownika. Ogólnie można to zrobić na 3 sposoby:

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

Zmniejsz rozmiar zasobu

Zasobem LCP strony (jeśli go zawiera) jest obraz lub czcionka internetowa. Poniższe przewodniki zawierają bardzo szczegółowe informacje na temat zmniejszenia rozmiaru obu typów plików:

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

Oprócz zmniejszenia rozmiaru zasobu możesz też skrócić czas wczytywania, umieszczając serwery jak najbliżej użytkowników. Najlepiej jest użyć sieci dostarczania treści (CDN).

Szczególnie pomocne są sieci CDN na potrzeby obrazów, ponieważ nie tylko zmniejszają odległość, jaką musi pokonać zasób, ale też zasadniczo zmniejszają jego rozmiar, automatycznie wdrażając za Ciebie wszystkie wcześniejsze zalecenia dotyczące zmniejszenia rozmiaru.

Zmniejszenie rywalizacji o przepustowość sieci

Nawet jeśli rozmiar zasobu jest mniejszy, a jego zasięg jest mniejszy, ładowanie zasobu może trwać dość długo, jeśli ładowanie się odbywa się z wielu innych zasobów w tym samym czasie. Ten problem jest znany jako rywalizacja z siecią.

Jeśli Twój zasób LCP ma wysoki wskaźnik fetchpriority i jak najszybciej zaczniesz go ładować, przeglądarka dołoży wszelkich starań, aby zapobiec konkurowaniu z zasobami o niższym priorytecie. Jeśli jednak ładujesz wiele zasobów z wysoką wartością fetchpriority lub po prostu wczytujesz dużo zasobów, może to mieć wpływ na szybkość ładowania zasobów LCP.

Całkowicie wyeliminuj czas pracy sieci

Najlepszym sposobem na skrócenie czasu wczytywania zasobów jest całkowite wyeliminowanie sieci z 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, zobaczą je z pamięci podręcznej, co w zasadzie spowoduje, że czas trwania ich obciążenia będzie wynosić zero.

Jeśli zasób LCP to czcionka internetowa, oprócz zmniejszenia rozmiaru czcionki internetowej musisz też wziąć pod uwagę blokowanie renderowania przy wczytywaniu takich zasobów. Jeśli ustawisz wartość font-display inną niż auto lub block, tekst będzie zawsze widoczny podczas wczytywania, a LCP nie będzie blokowany w przypadku dodatkowego żądania sieciowego.

Jeśli zasób LCP jest mały, warto wbudować je w adres URL danych, co wyeliminuje dodatkowe żądania sieciowe. Używanie adresów URL danych ma jednak pewne ograniczenia, ponieważ zasoby nie mogą być przechowywane w pamięci podręcznej, a w niektórych przypadkach mogą prowadzić do dłuższych opóźnień renderowania z powodu dodatkowych kosztów 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ż często nad nim najmniejszą kontrolę mają deweloperzy. Jest to jednak również jeden z najważniejszych kroków, ponieważ ma bezpośredni wpływ na każdy następny krok. Nic nie może się stać w frontendzie, dopóki backend nie dostarczy pierwszego bajtu treści, więc wszystko, co możesz zrobić, aby przyspieszyć przetwarzanie TTFB, poprawi także wszystkie pozostałe dane o obciążeniu.

Częstą przyczyną powolnego zamiany tekstu na mowę w innej witrynie jest często klikanie wielu przekierowań, na przykład dzięki reklamom lub skróconym linkom. Zawsze ogranicz liczbę przekierowań, które musi czekać użytkownik.

Inną częstą przyczyną jest sytuacja, w której treści przechowywanej w pamięci podręcznej nie można używać z serwera brzegowego CDN, a wszystkie żądania muszą być kierowane z powrotem na serwer pierwotny. Może się tak zdarzyć, jeśli do celów analitycznych używają unikalnych parametrów adresu URL – nawet jeśli nie powodują one otwarcia różnych stron.

Szczegółowe wskazówki dotyczące optymalizacji TTFB znajdziesz w przewodniku po optymalizacji TTFB.

Monitorowanie rozkładu LCP w JavaScript

Informacje o czasie wszystkich omówionych wcześniej podczęści LCP są dostępne w języku JavaScript dzięki połączeniu tych interfejsów API wydajności:

Zaletą przetwarzania tych wartości czasu w języku JavaScript jest możliwość wysłania ich do dostawcy usług analitycznych lub zarejestrowania ich w narzędziach dla programistów, co ułatwi debugowanie i optymalizację.

Na przykład poniższy zrzut ekranu wykorzystuje metodę performance.measure() z interfejsu User Timing API w celu dodania słupków do ścieżki Timings w panelu wydajności Chrome DevTools.

Pomiary czasu działań użytkowników w podkategoriach LCP wizualizowanych w Narzędziach deweloperskich w Chrome
Ścieżka Czasy zawiera ramy czasowe dla podkategorii LCP.

Wizualizacje na ścieżce Czasy są szczególnie przydatne, gdy analizujesz ścieżki Sieć i Wątek główny, ponieważ możesz szybko sprawdzić, co jeszcze dzieje się na stronie w tych przedziałach czasu.

Oprócz wizualizowania podczęści LCP na ścieżce czasowej możesz też użyć JavaScriptu, aby obliczyć, jaki procent czasu LCP odpowiada każdej z nich. Dzięki tym informacjom możesz określić, czy Twoje strony spełniają opisane wcześniej zalecane podziały procentowe.

Ten zrzut ekranu pokazuje przykład, który rejestruje łączny czas każdej podczęści LCP, a także procent łącznego czasu LCP w konsoli.

Czas podkategorii LCP oraz ich procentowy udział w LCP są wyświetlane w konsoli.
Czasy i wartości procentowe 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 duration',
  '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 takiej postaci do lokalnego debugowania lub zmodyfikować go, aby wysyłać dane do dostawcy usług analitycznych, co pozwoli Ci lepiej zrozumieć rozkład LCP na Twoich stronach w przypadku rzeczywistych użytkowników.

Monitoruj statystyki LCP za pomocą rozszerzenia Wskaźniki internetowe

Rozszerzenie Web Vitals rejestruje czas LCP, element LCP i te 4 podczęści w konsoli, aby ułatwić Ci zrozumienie tego podziału.

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.

Podsumowanie

Wartość LCP jest złożona, a jej czas zależy od wielu czynników. Jeśli jednak weźmiesz pod uwagę, że optymalizacja LCP koncentruje się przede wszystkim na optymalizacji obciążenia zasobów LCP, może to znacznie uprościć sprawę.

Ogólnie optymalizację LCP można podsumować w 4 krokach:

  1. Zadbaj o to, aby zasób LCP zaczął ładować się jak najwcześniej.
  2. Dopilnuj, aby element LCP mógł zostać wyrenderowany, gdy tylko zakończy się wczytywanie jego zasobu.
  3. Jak najbardziej skróć czas wczytywania zasobu LCP bez negatywnego wpływu na jakość.
  4. Dostarczaj początkowy dokument HTML tak szybko, jak to możliwe.

Jeśli możesz wykonać te czynności na swoich stronach, możesz mieć pewność, że zapewniasz użytkownikom optymalne wrażenia podczas wczytywania, a odzwierciedlenie to w rzeczywistych wynikach LCP.