Optymalizacja największego wyrenderowania treści

Szczegółowy przewodnik, z którego dowiesz się, jak podzielić LCP i wskazać kluczowe obszary wymagające poprawy.

Data publikacji: 30 kwietnia 2020 r.

Największe wyrenderowanie treści (LCP) to jeden z 3 podstawowych wskaźników internetowych i wskazuje, jak szybko wczytuje się główna zawartość strony internetowej. Wskaźnik LCP mierzy czas od momentu, gdy użytkownik rozpoczyna wczytywanie strony, do momentu wyrenderowania największego obrazu lub bloku tekstu w widocznym obszarze.

W trosce o wygodę użytkowników wskaźnik LCP witryny powinien wynosić nie więcej niż 2, 5 sekundy w przypadku co najmniej 75% wizyt.

Dobre wartości LCP wynoszą maksymalnie 2,5 sekundy, niskie wartości powyżej 4,0 sekund, a niektóre z nich wymagają poprawy
Dobra wartość LCP wynosi maksymalnie 2,5 sekundy.

Na szybkość wczytywania i renderowania strony internetowej przez przeglądarkę 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 zdarza się, aby szybka poprawa jednego elementu strony spowodowała istotną poprawę wskaźnika LCP. Aby poprawić LCP, trzeba przyjrzeć się całemu procesowi wczytywania i upewnić się, że każdy jego etap jest zoptymalizowany.

Jak interpretować wskaźnik LCP

Przed zoptymalizowaniem LCP deweloperzy powinni się dowiedzieć, czy mają w ogóle problemy z LCP i jaki jest ich zakres.

LCP można mierzyć za pomocą wielu narzędzi, ale nie wszystkie z nich mierzą go w ten sam sposób. Aby zrozumieć LCP rzeczywistych użytkowników, powinniśmy przyjrzeć się temu, jak czują się oni podczas korzystania z witryny, a nie temu, co pokazuje narzędzie laboratoryjne, takie jak Lighthouse, lub testy lokalne. Te laboratoryjne narzędzia mogą dostarczyć mnóstwo informacji, które pomogą Ci zrozumieć i poprawić LCP. Pamiętaj jednak, że same testy laboratoryjne mogą nie być całkowicie reprezentatywne dla rzeczywistych użytkowników.

Dane LCP na podstawie rzeczywistych użytkowników można uzyskać z narzędzi do monitorowania użytkowników (RUM) zainstalowanych w witrynie lub z 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 w raporcie CrUX w PageSpeed Insights

Narzędzie PageSpeed Insights umożliwia dostęp do danych raportu CrUX w górnej sekcji oznaczonej etykietą Dowiedz się, co robią użytkownicy. Bardziej szczegółowe dane z testów laboratoryjnych są dostępne w sekcji na dole o nazwie Diagnoza problemów z wydajnością. Jeśli dane raportu na temat użytkowania Chrome są dostępne w przypadku Twojej witryny, w pierwszej kolejności skoncentruj się na prawdziwych danych użytkownika.

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

PageSpeed Insights może wyświetlać maksymalnie cztery różne dane raportu CrUX:

  • Mobilna transmisja danych dla tego adresu URL
  • Dane dotyczące komputera dotyczące tego adresu URL
  • Mobilna transmisja danych dla całego obszaru Origin
  • Dane dla komputerów dla całego obszaru Origin

Możesz to zrobić za pomocą elementów sterujących w prawym górnym i prawym górnym rogu tej sekcji. Jeśli adres URL nie ma wystarczającej ilości danych, aby wyświetlić je na poziomie adresu URL, ale ma dane źródłowe, narzędzie PageSpeed Insights zawsze wyświetla dane źródłowe.

W przypadku braku danych na poziomie adresu URL narzędzie PageSpeed Insights korzysta z danych na poziomie źródła
Jeśli narzędzie PageSpeed Insights nie ma danych na poziomie adresu URL, pokazuje dane na poziomie źródła.

Wartość LCP całego punktu początkowego może się znacznie różnić od LCP pojedynczej strony w zależności od tego, jak LCP jest wczytywany na tej stronie w porównaniu z innymi stronami w tej witrynie. To również sposób, w jaki użytkownicy przechodzą do tych stron. Strony główne są zwykle odwiedzane przez nowych użytkowników, dlatego często są wczytywane „na zimno”, bez treści w pamięci podręcznej, co powoduje, że są to często najwolniejsze strony w witrynie.

Analiza 4 różnych kategorii danych z CrUX może pomóc Ci ustalić, czy problem z LCP dotyczy tylko tej strony, czy też jest bardziej ogólnym problemem w całej witrynie. Może też pokazać, na jakich typach urządzeń występują problemy z LCP.

Korzystanie z danych uzupełniających CrUX w PageSpeed Insights

Osoby, które chcą zoptymalizować LCP, powinny też korzystać z czasów Pierwsze wyrenderowanie treści (FCP) i Czas do pierwszego bajtu (TTFB). Są to dobre dane diagnostyczne, które dostarczają cennych informacji o LCP.

TTFB to czas od momentu, gdy użytkownik rozpoczyna nawigację po stronie (np. klika link), do momentu, gdy otrzymane zostaną pierwsze bajty dokumentu HTML. Wysoki wskaźnik TTFB może sprawić, że uzyskanie 2,5-sekundowego LCP będzie trudne, a nawet niemożliwe.

Długi czas TTFB może być spowodowany wieloma przekierowaniami na serwer, lokalizacją użytkowników daleko od najbliższego serwera witryny, niekorzystnymi warunkami sieci lub brakiem możliwości korzystania z treści w pamięci podręcznej z powodu parametrów zapytania.

Po rozpoczęciu renderowania strony może być początkowo wyrenderowane (np. kolor tła), a potem pojawi się jakaś treść (np. nagłówek witryny). Wygląd początkowych treści jest mierzony za pomocą wskaźnika FCP. Różnica między FCP a innymi wskaźnikami może być bardzo znacząca.

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 też oznaczać, że musi on wykonać dużo pracy, aby wyrenderować dowolne treści – klasyczny znak, że witryna w dużej mierze polega na renderowaniu po stronie klienta.

Duża różnica między FCP a LCP oznacza, że zasób LCP nie jest od razu dostępny dla przeglądarki, aby ustalić priorytety (np. tekst lub obrazy zarządzane przez JavaScript, a nie dostępne w początkowym kodzie HTML), albo że przeglądarka wykonuje coś innego, zanim wyświetli treść LCP.

Korzystanie z danych Lighthouse w PageSpeed Insights

Sekcja Lighthouse w narzędziu PageSpeed Insights zawiera wskazówki dotyczące poprawy LCP, ale najpierw sprawdź, czy LCP jest zgodny z danymi o prawdziwych użytkownikach pochodzącymi z raportu CrUX. Jeśli narzędzia Lighthouse i CrUX się nie zgadzają, prawdopodobnie CrUX zapewnia dokładniejszy obraz wrażeń użytkownika. Przed wykonaniem działania upewnij się, że dane raportu na temat użytkowania Chrome dotyczą Twojej strony, a nie jej pełnego pochodzenia.

Jeśli zarówno w LCP, jak i w raporcie CrUX wyświetlają się wartości LCP, które wymagają poprawy, w sekcji dotyczącej narzędzia Lighthouse znajdziesz cenne wskazówki, jak poprawić LCP. Użyj filtra LCP, aby wyświetlać tylko audyty dotyczące LCP w ten sposób:

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

Oprócz możliwości ulepszenia masz też dostęp do informacji diagnostycznych, które mogą zawierać więcej informacji, które pomogą zdiagnozować problem. Diagnostyka elementu największego wyrenderowania treści pokazuje przydatne zestawienie różnych momentów składających się na LCP:

Etapy LCP w Lighthouse
Podział elementów LCP w narzędziu Lighthouse.

Omówimy je teraz.

Podział według LCP

Optymalizacja LCP może być bardziej skomplikowanym zadaniem, jeśli narzędzie PageSpeed Insights nie podaje sposobu na poprawę tego wskaźnika. W przypadku złożonych zadań lepiej jest podzielić je na mniejsze, łatwiejsze do wykonania zadania i rozwiązać je z osobna.

W tej sekcji przedstawiamy metodę dzielenia LCP na najważniejsze podelementy, a następnie podajemy konkretne rekomendacje i sprawdzone metody dotyczące optymalizacji poszczególnych części.

Większość ładowań stron obejmuje zwykle pewną liczbę żądań sieciowych, ale dla identyfikacji możliwości poprawy LCP należy zacząć od przeanalizowania tylko 2 z nich:

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

Chociaż inne żądania ze strony mogą wpływać na LCP, te 2 – zwłaszcza 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 wspomniane wcześniej PageSpeed Insights, Narzędzie deweloperskie w Chrome lub WebPageTest), aby określić element LCP. Możesz tam dopasować adres URL (ponownie, w stosownych przypadkach) wczytany przez element w splacie sieci wszystkich zasobów załadowanych przez stronę.

Na przykład na tej wizualizacji te zasoby są wyróżnione na diagramie kaskady sieci podczas typowego wczytywania strony, gdy element LCP wymaga przesłania żądania obrazu.

Kaskada sieci z wyróżnionymi zasobami HTML i LCP
Schemat kaskady przedstawiający czasy wczytywania dla w kodzie HTML strony i zasobach wymaganych przez LCP.

W przypadku dobrze zoptymalizowanej strony żądanie zasobu LCP powinno się zacząć wczytywać jak najwcześniej, a element LCP powinien zostać wyrenderowany tak szybko, jak to możliwe po zakończeniu wczytywania zasobu LCP. Aby zobrazować, czy dana strona przestrzega tej zasady, możesz podzielić łączny czas LCP na te części:

Czas do pierwszego bajtu (TTFB)
Czas od momentu zainicjowania wczytywania strony przez użytkownika do chwili, gdy przeglądarka otrzyma pierwszy bajt odpowiedzi dokumentu HTML.
Opóźnienie ładowania zasobów
Czas między czasem TTFB a momentem, gdy przeglądarka rozpoczyna wczytywanie zasobu LCP. Jeśli renderowanie elementu LCP nie wymaga wczytania zasobów (np. gdy element jest węzłem tekstowym renderowanym za pomocą czcionki systemowej), czas ten wynosi 0.
Czas wczytywania zasobu
Czas potrzebny na wczytanie zasobu LCP. Jeśli LCP nie wymaga wczytania zasobu do renderowania, ten czas ma wartość 0.
Opóźnienie renderowania elementu
Czas od zakończenia wczytywania zasobu LCP do pełnego wyrenderowania elementu LCP.

LCP każdej strony składa się z tych 4 podkategorii. Rozwiązania nie pokrywają się z żadnymi różnicami i sumują się do łącznego czasu LCP.

Wyszczególnienie LCP z 4 podkategoriami
Ten sam diagram kaskadowy z 4 podkategoriami LCP nałożonymi na osi czasu.

Wartość LCP każdej strony można podzielić na cztery części. Nie ma między nimi żadnych przerw ani luk. Suma tych wartości jest równa pełnej wartości LCP.

Przy optymalizowaniu LCP warto spróbować zoptymalizować te części z osobna. Pamiętaj jednak, że musisz zoptymalizować wszystkie z nich. W niektórych przypadkach optymalizacja w jednej części nie poprawi LCP, a jedynie przeniesie zaoszczędzony czas w innej części.

Na przykład we wcześniejszej kaskadzie sieci – jeśli zmniejszysz rozmiar pliku obrazu przez większe skompresowanie lub przejście do bardziej optymalnego formatu (takiego jak AVIF lub WebP), skrócenie czasu wczytywania zasobu nie poprawiłoby jednak LCP, ponieważ czas ten zostałby przesunięty do podczęści opóźnienia renderowania elementu:

Ten sam rozkład LCP, w którym podkategoria czasu wczytywania zasobów jest skrócona, ale ogólny czas LCP pozostaje bez zmian.
Skrócenie czasu ładowania zasobów zwiększa opóźnienie renderowania elementu bez zmniejszania wartości LCP.

Dzieje się tak, ponieważ na tej stronie element LCP jest ukryty, dopóki nie zakończy się wczytywanie kodu JavaScript, a potem wszystko jest odsłaniane naraz.

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

Optymalne czasy częściowych elementów

Aby zoptymalizować każdą część LCP, trzeba wiedzieć, jak idealny rozkład tych części jest odpowiedni na dobrze zoptymalizowanej stronie.

Dwie z czterech części noszą słowo „opóźnienie”. w ich nazwach. To wskazówka, że chcesz, aby te czasy były jak najbliższe zeru. Pozostałe 2 części dotyczą żądań sieci, które z samej swojej natury zajmują trochę czasu.

Część podrzędna LCP % LCP
Czas do pierwszego bajtu ok. 40%
Opóźnienie ładowania zasobów <10%
Czas wczytywania zasobu ok. 40%
Opóźnienie renderowania elementu <10%
RAZEM 100%

Pamiętaj, że te przedziały czasowe są wskazówkami, a nie ścisłymi zasadami. Jeśli czasy LCP na stronach są konsekwentnie w zakresie 2,5 sekundy, nie ma większego znaczenia, jakie są względne proporcje. Jeśli jednak spędzasz dużo czasu w opóźnieniach, bardzo trudno będzie osiągnąć cel 2, 5 sekundy.

Oto prawidłowy sposób przedstawienia rozkładu czasu LCP:

  • Większość czasu LCP powinna być poświęcona na wczytywanie dokumentu HTML i źródła LCP.
  • Każdy moment przed LCP, w którym jeden z tych 2 zasobów nie się wczytuje, stanowi szansę na ulepszenie.
.

Jak optymalizować poszczególne części

Teraz, gdy już wiesz, jak poszczególne czasy ładowania elementów LCP powinny się rozkładać na dobrze zoptymalizowanej stronie, możesz zacząć optymalizować własne strony.

Kolejne cztery sekcje zawierają zalecenia i sprawdzone metody optymalizacji każdej części. Są one prezentowane w odpowiedniej kolejności, zaczynając od optymalizacji, która prawdopodobnie będzie najbardziej skuteczna.

1. Eliminowanie opóźnienia wczytywania zasobów

W tym kroku należy zadbać o to, aby zasób LCP jak najwcześniej zaczął się ładować. Chociaż teoretycznie zasób może zacząć się wczytywać zaraz po zakończeniu TTFB, w praktyce zawsze występuje pewne opóźnienie, zanim przeglądarki zaczną wczytywać zasoby.

Zasada jest taka, że zasób LCP powinien zacząć się wczytywać w tym samym czasie co pierwszy zasób wczytywany przez stronę. Inaczej mówiąc, jeśli zasób LCP zacznie się wczytywać później niż pierwszy zasób, będzie można go ulepszyć.

Schemat kaskadowy sieci przedstawiający zasób LCP zaczynający się po pierwszym zasobie, pokazujący możliwości poprawy
Na tej stronie zasób LCP zaczyna ładować się odpowiednio po zastosowaniu stylu arkusza, który zostanie wczytany jako pierwszy. Jest tu miejsce na poprawę.

Ogólnie rzecz biorąc, na szybkość wczytywania zasobu LCP wpływają 2 czynniki:

  • Gdy zasób zostanie wykryty.
  • Priorytet, który ma mieć zasób.

Optymalizuj po wykryciu zasobu

Aby zasób LCP ładował się jak najwcześniej, musi on być wykrywalny w początkowej odpowiedzi na dokument HTML przez skaner wstępnego wczytywania przeglądarki. Na przykład w następujących przypadkach przeglądarka może wykryć zasób LCP, skanując odpowiedź dokumentu HTML:

  • Element LCP jest elementem <img>, a jego atrybuty src i srcset znajdują się w początkowych znacznikach HTML.
  • Element LCP wymaga tła CSS, ale jest ono wstępnie wczytywane za pomocą atrybutu <link rel="preload"> w znaczniku HTML (lub za pomocą nagłówka Link).
  • Element LCP to węzeł tekstowy, który wymaga do renderowania czcionki internetowej, a czcionka jest ładowana za pomocą <link rel="preload"> w znacznikach HTML (lub za pomocą nagłówka Link).

Oto kilka przykładów sytuacji, w których zasób LCP nie może zostać wykryty podczas skanowania odpowiedzi dokumentu HTML:

  • Element LCP to <img>, który jest dynamicznie dodawany do strony za pomocą JavaScriptu.
  • Element LCP jest ładowany z opóźnieniem za pomocą biblioteki 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 wymaga oczekiwania na zakończenie żądań sieciowych), zanim wykryje zasób LCP i zacznie go wczytywać. To nigdy nie jest optymalne.

Aby wyeliminować niepotrzebne opóźnienie wczytywania zasobów, zasób LCP powinien być wykrywalny w źródle HTML. W przypadku zasobów, do których odwołuje się tylko zewnętrzny plik CSS lub JavaScript, zasób LCP powinien być wstępnie ładowany z wysokim priorytetem pobierania, na przykład:

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

Zoptymalizuj priorytet przydzielanego zasobu

Nawet jeśli zasób LCP jest wykrywalny na podstawie znaczników HTML, nadal może nie zacząć się wczytywać wcześniej niż pierwszy zasób. Może się tak zdarzyć, gdy heurystyka priorytetowa skanera w przeglądarce nie rozpozna, że zasób jest ważny, lub jeśli ustali, ż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". Użycie leniwego wczytywania oznacza, że zasób nie zostanie załadowany, dopóki układ nie potwierdzi, że obraz znajduje się w widoku, więc może zacząć się wczytywać później niż w przypadku braku leniwego wczytywania.

Nawet bez leniwego ładowania obrazy nie są początkowo wczytywane z najwyższym priorytetem, ponieważ nie są to zasoby blokujące renderowanie. Możesz zasugerować przeglądarce, które zasoby są najważniejsze, używając atrybutu fetchpriority w przypadku zasobów, które mogą korzystać z wyższego priorytetu:

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

Jeśli uważasz, że element <img> może być elementem LCP strony, warto ustawić dla niego parametr fetchpriority="high". Ustawienie wysokiego priorytetu dla więcej niż 1 lub 2 obrazów powoduje jednak, że ustawienie priorytetu nie pomaga w zmniejszeniu LCP.

Możesz też obniżyć priorytet obrazów, które mogą być na początku odpowiedzi na dokument, ale nie są widoczne ze względu na stylizację, np. obrazów na slajdach w karuzeli, które nie są widoczne na początku:

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

Zmniejszenie priorytetu niektórych zasobów może zapewnić większą przepustowość dla zasobów, które ich bardziej potrzebują, ale zachowaj ostrożność. Zawsze sprawdzaj priorytet zasobów w Narzędziach deweloperskich i testuj zmiany za pomocą narzędzi do testowania w laboratorium i w terenie.

Po optymalizacji priorytetu zasobu LCP i czasu wykrywania wodospad sieci powinien wyglądać tak (zasób LCP uruchamia się w tym samym czasie co pierwszy zasób):

Diagram kaskady sieciowy przedstawiający zasób LCP, który rozpoczyna się w tym samym momencie co pierwszy zasób
zasób LCP zaczyna się teraz wczytywać w tym samym czasie co arkusz stylów.
.

2. Wyeliminuj opóźnienie renderowania elementu.

Celem tego kroku jest zapewnienie, aby element LCP mógł zostać wyrenderowany 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 jego zasobu, jest to, że renderowanie jest blokowane z jakiegoś innego powodu:

  • Renderowanie całej strony jest zablokowane z powodu wczytywania się arkuszy stylów lub skryptów synchronicznych w elementach <head>.
  • Zasób LCP został wczytany, ale element LCP nie został jeszcze dodany do modelu DOM (czeka na wczytanie kodu JavaScript).
  • Element jest ukryty przez inny kod, np. bibliotekę testów A/B, która wciąż określa, w jakim eksperymencie powinien uczestniczyć użytkownik.
  • Wątek główny jest zablokowany z powodu długich zadań, a renderowanie musi zaczekać na zakończenie tych długich zadań.

W sekcjach poniżej wyjaśniamy, jak radzić sobie z najczęstszymi przyczynami niepotrzebnego opóźnienia renderowania elementu.

Ogranicz lub wbudowane arkusze stylów blokujące renderowanie

Arkusze stylów wczytane za pomocą znaczników HTML będą blokować renderowanie całej treści, która następuje po nich, co jest dobrą zasadą, ponieważ zazwyczaj nie chcesz renderować kodu HTML bez stylu. Jeśli jednak arkusz stylów jest tak duży, że jego wczytanie zajmuje znacznie więcej czasu niż zasób LCP, uniemożliwi to renderowanie elementu LCP, nawet po zakończeniu wczytywania zasobu, jak w tym przykładzie:

Diagram siatki sieci pokazujący duży plik CSS blokujący renderowanie elementu LCP, ponieważ jego wczytanie zajmuje więcej czasu niż zasób LCP
Wczytywanie obrazu i arkusza stylów rozpoczyna się jednocześnie, ale nie można go wyrenderować, dopóki arkusz stylów nie będzie gotowy.

Aby rozwiązać ten problem, możesz:

  • wstawić arkusz stylów bezpośrednio w pliku HTML, aby uniknąć dodatkowego żądania sieciowego;
  • aby zmniejszyć rozmiar arkusza stylów.

Ogólnie zalecamy wbudowanie arkusza stylów tylko wtedy, gdy jest on mały, ponieważ treść wbudowana w kodzie HTML nie może korzystać z buforowania przy kolejnych wczytywaniu stron. Jeśli arkusz stylów jest tak duży, że jego wczytywanie trwa dłużej niż zasób LCP, raczej nie nadaje się do wbudowania.

W większości przypadków najlepszym sposobem na upewnienie się, że arkusz stylów nie blokuje renderowania elementu LCP, jest zmniejszenie jego rozmiaru, tak aby był on mniejszy niż zasób LCP. Dzięki temu nie stanowi ono wąskiego gardła dla większości wizyt.

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

Odrocz lub wbudowany kod JavaScript blokujący renderowanie

Dodawanie skryptów synchronicznych (bez atrybutów async lub defer) do <head> stron jest prawie nigdy niepotrzebne i prawie zawsze ma negatywny wpływ na wydajność.

Jeśli kod JavaScript musi być wykonywany jak najwcześniej podczas wczytywania strony, najlepiej umieścić go w kodze HTML, aby nie opóźniać renderowania przez oczekiwanie na kolejne żądanie sieci. Podobnie jak w przypadku arkuszy stylów, skrypty powinny być wstawiane w postaci kodu tylko wtedy, gdy są bardzo małe.

Nie
<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żyj 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 za pomocą pełnych znaczników HTML.

Z punktu widzenia optymalizacji LCP, SSR ma 2 główne zalety:

  • Zasoby obrazów będzie można znaleźć w źródle HTML (jak omówiono w kroku 1 wcześniej).
  • Treści strony nie będą wymagać dodatkowych żądań JavaScript, aby mogły zostać wyrenderowane.

Główną wadą SSR jest konieczność wydłużenia czasu przetwarzania danych, co może spowolnić działanie funkcji TTFB. Takie rozwiązanie jest zwykle opłacalne, ponieważ czas przetwarzania serwera jest pod Twoją kontrolą, podczas gdy na możliwości sieci i urządzeń użytkowników nie masz wpływu.

Opcja podobna do SSR to generowanie witryn statycznych (SSG) lub renderowanie wstępne. Jest to proces generowania stron HTML na etapie kompilacji, a nie na żądanie. Jeśli w Twojej architekturze jest możliwe prerenderowanie, jest to zazwyczaj lepszy wybór pod kątem wydajności.

Dzielenie długich zadań

Nawet jeśli po zastosowaniu się do wcześniejszych wskazówek kod JavaScript nie blokuje renderowania i nie jest odpowiedzialny za renderowanie elementów, nadal może opóźniać LCP.

Najczęstszą przyczyną takiej sytuacji 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 wtedy, gdy zasób obrazu został w pełni pobrany, przed renderowaniem może on nadal czekać na zakończenie wykonywania niepowiązanego skryptu.

Obecnie wszystkie przeglądarki renderują 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 zasobów

Celem tego kroku jest skrócenie czasu przesyłania 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;
  • całkowicie wyeliminować czas sieci;

Zmniejsz rozmiar zasobu

Zasób LCP strony (jeśli taki istnieje) to obraz lub czcionka internetowa. W tych przewodnikach szczegółowo opisujemy, jak zmniejszyć rozmiar obu tych elementów:

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

Poza zmniejszeniem rozmiaru zasobu można także zmniejszyć czas wczytywania przez ustawienie serwerów jak największej odległości od użytkowników. Najlepszym sposobem jest skorzystanie z sieci dostarczania treści (CDN).

CDN obrazów są szczególnie przydatne, ponieważ nie tylko zmniejszają odległość, jaką musi pokonać zasób, ale także ogólnie zmniejszają jego rozmiar, automatycznie stosując w Twoim imieniu wszystkie wcześniejsze rekomendacje dotyczące zmniejszania rozmiaru.

Zmniejsz rywalizację o przepustowość sieci

Nawet jeśli zmniejszysz rozmiar zasobu i zmniejszysz jego odległość, wczytywanie zasobu może jeszcze długo trwać, jeśli wczytujesz wiele innych zasobów jednocześnie. Ten problem jest znany jako rywalizacja sieci.

Jeśli zasób LCP ma wysoki poziom fetchpriority i rozpocznie się ładowanie tak szybko, jak to możliwe, przeglądarka będzie starała się zapobiec konkurowaniu z nim zasobów o niższym priorytecie. Jeśli jednak wczytujesz wiele zasobów o wysokiej wartości fetchpriority lub po prostu wczytujesz dużo zasobów, może to wpłynąć na szybkość wczytywania zasobu LCP.

całkowite wyeliminowanie czasu sieci;

Najlepszym sposobem na skrócenie czasu obciążenia zasobów jest całkowite wykluczenie sieci z procesu. Jeśli zasoby są dostarczane zgodnie z skuteczną zasadą kontroli pamięci podręcznej, użytkownicy, którzy po raz drugi poproszą o te zasoby, otrzymają je z pamięci podręcznej. W ten sposób czas wczytywania zasobów będzie praktycznie zerowy.

Jeśli zasób LCP to czcionka internetowa, oprócz zmniejszenia rozmiaru czcionki internetowej musisz też wziąć pod uwagę, czy nie musisz blokować renderowania podczas wczytywania tych zasobów. Jeśli wartość atrybutu font-display jest inna niż auto lub block, tekst będzie zawsze widoczny podczas wczytywania, a LCP nie będzie blokowane w dodatkowym żądaniu sieci.

I wreszcie, jeśli zasób LCP jest mały, warto je wbudować w adres URL danych, co pozwoli uniknąć dodatkowego żądania sieciowego. Używanie adresów URL danych wymaga jednak ostrożności, ponieważ zasoby nie mogą być przechowywane w pamięci podręcznej, a w niektórych przypadkach może to spowodować dłuższe opóźnienia w renderowaniu z powodu dodatkowego kosztu dekodowania.

4. Skróć czas do pierwszego bajtu

Celem tego etapu jest jak najszybsze dostarczenie początkowego kodu HTML. Ten krok jest wymieniony na końcu, ponieważ często nad nim deweloper ma najmniejszą kontrolę. Jest to jednak również jeden z najważniejszych kroków, ponieważ wpływa bezpośrednio na każdy kolejny krok. Dopóki backend nie prześle pierwszego bajta treści, nic nie może się dziać po stronie front-endu. Dlatego wszystko, co możesz zrobić, aby przyspieszyć TTFB, poprawi też wszystkie inne wskaźniki wczytywania.

Częstą przyczyną powolnego działania funkcji TTFB w przypadku witryn, które są niezbyt szybko szybkie, są wielokrotne przekierowania, np. z reklam lub skróconych linków. Zawsze minimalizuj liczbę przekierowań, które musi przejść użytkownik.

Inną częstą przyczyną jest sytuacja, gdy nie można użyć treści z pamięci podręcznej z serwera brzegowego CDN, a wszystkie żądania muszą być kierowane z powrotem do serwera źródłowego. Może się tak zdarzyć, jeśli unikalne parametry adresu URL będą wykorzystywane przez użytkowników do celów analitycznych – nawet jeśli nie prowadzą do różnych stron.

Szczegółowe wskazówki dotyczące optymalizacji czasu oczekiwania na odpowiedź znajdziesz w przewodniku po optymalizacji czasu oczekiwania na odpowiedź.

Monitorowanie podziału LCP w JavaScript

Informacje o czasie dla wszystkich omówionych wcześniej podpunktów LCP są dostępne w języku JavaScript za pomocą kombinacji tych interfejsów API do kontrolowania wydajności:

Wyliczanie tych wartości w JavaScriptzie ma tę zaletę, że możesz wysyłać je do dostawcy usługi analitycznej lub rejestrować w narzędziach dla programistów, aby ułatwić debugowanie i optymalizowanie.

Na przykład ten zrzut ekranu korzysta z metody performance.measure() z interfejsu User Timing API w celu dodania słupków do ścieżki czasu w panelu Skuteczność w Narzędziach deweloperskich w Chrome.

Pomiary czasu użytkownika dotyczące podkategorii LCP wizualizowanych w Narzędziach deweloperskich w Chrome
Ścieżka Czasy pokazuje osie czasu dla podkategorii LCP.

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

Oprócz wizualizacji podczęści LCP na ścieżce czasu możesz też użyć JavaScriptu do obliczania procentu poszczególnych części składowych LCP w całkowitym czasie LCP. Na podstawie tych informacji możesz sprawdzić, czy Twoje strony spełniają zalecane podziały na odsetki opisane wcześniej.

Na tym zrzucie ekranu widać przykład, w którym rejestrowany jest łączny czas każdej części LCP, a także jego odsetek dla łącznego czasu LCP w konsoli.

Godziny podkategorii LCP i ich odsetek LCP, które są wyświetlane w konsoli.
Czasy ładowania i odsetek użytkowników w podkategoriach LCP.

Obie 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 niezmienionej formie do lokalnego debugowania lub zmodyfikować go, aby wysyłać te dane do dostawcy usług analitycznych, co pozwoli Ci lepiej zrozumieć, jak rozkładają się LCP na Twoich stronach dla rzeczywistych użytkowników.

Monitorowanie wartości LCP za pomocą Narzędzi deweloperskich w Chrome

Narzędzia deweloperskie w Chrome będą w czasie rzeczywistym rejestrować czas LCP, element LCP oraz te 4 podelementy, aby umożliwić Ci wyświetlanie tego zestawienia.

Czasy poszczególnych części LCP w panelu wydajności w Narzędziach deweloperskich w Chrome
Czasy trwania poszczególnych części LCP w panelu Performance w Narzędziach deweloperskich w Chrome.

Podsumowanie

LCP to złożony wskaźnik, a na jego czas realizacji może wpływać wiele czynników. Jeśli jednak weźmiemy pod uwagę, że optymalizacja LCP polega głównie na optymalizacji obciążenia zasobów LCP, może to znacznie uprościć cały proces.

Ogólnie rzecz biorąc, optymalizację LCP można podsumować w 4 kroki:

  1. Upewnij się, że zasób LCP zaczyna się ładować jak najwcześniej.
  2. Upewnij się, że element LCP może zostać wyświetlony, gdy tylko jego zasób zostanie wczytany.
  3. Skróć czas wczytywania zasobu LCP jak najbardziej bez negatywnego wpływu na jakość.
  4. Prześlij jak najszybciej początkowy dokument HTML.

Jeśli wykonasz te czynności na swoich stronach, będziesz mieć pewność, że proces ładowania strony przebiega optymalnie, co powinno być widoczne w rzeczywistych wynikach LCP.