W przeszłości webmasterzy mierzyli się z wyzwaniem, jakim jest pomiar szybkości wczytywania i widoczności głównej zawartości strony internetowej dla użytkowników. Starsze dane, takie jak load czy DOMContentLoaded, nie sprawdzają się dobrze, ponieważ niekoniecznie odpowiadają temu, co użytkownik widzi na ekranie. Nowsze dane o wydajności zorientowane na użytkownika, takie jak pierwsze wyrenderowanie treści (FCP), rejestrują tylko początek wczytywania. Jeśli na stronie wyświetla się ekran powitalny lub wskaźnik wczytywania, ten moment nie jest zbyt istotny dla użytkownika.
W przeszłości zalecaliśmy wskaźniki wydajności, takie jak pierwsze wyrenderowanie treści (FMP) i indeks szybkości (SI) (oba dostępne w Lighthouse), aby pomóc w lepszym zobrazowaniu wczytywania po pierwszym wyrenderowaniu, ale te dane są skomplikowane, trudne do wyjaśnienia i często nieprawidłowe, ponieważ nadal nie określają, kiedy wczytano główne treści strony.
Na podstawie dyskusji w grupie roboczej W3C ds. wydajności stron internetowych oraz badań przeprowadzonych w Google stwierdziliśmy, że dokładniejszym sposobem pomiaru czasu wczytywania głównej zawartości strony jest sprawdzenie, kiedy renderowany jest największy element.
Co to jest LCP?
LCP wskazuje czas renderowania największego obrazu, bloku tekstu lub filmu wyświetlanego w widocznym obszarze w odniesieniu do czasu, w którym użytkownik po raz pierwszy otworzył stronę.
Jaki jest dobry wynik LCP?
Aby zapewnić użytkownikom wygodę, witryny powinny mieć czas największego wyrenderowania treści wynoszący 2,5 sekund lub krócej. Aby mieć pewność, że osiągasz ten cel w przypadku większości użytkowników, warto mierzyć 50. percentyl wczytywania stron podzielony na urządzenia mobilne i komputery.
Jakie elementy są brane pod uwagę?
Zgodnie z obecnie określoną w interfejsie API największego wyrenderowania treści listą typów elementów uwzględnianych w przypadku największego wyrenderowania treści:
<img>
(czas wyświetlania pierwszego kadru jest używany w przypadku treści animowanych, takich jak GIF-y lub animowane pliki PNG);- Elementy
<image>
w elementach<svg>
<video>
(używany jest czas wczytywania obrazu plakatu lub czas wyświetlania pierwszego kadru w przypadku filmów – w zależności od tego, co jest wcześniejsze);- Element z obrazem tła wczytanym za pomocą funkcji
url()
(w przeciwieństwie do gradientu CSS). - Elementy na poziomie bloku zawierające węzły tekstowe lub inne podrzędne elementy tekstowe wstawiane w tekście.
Ograniczenie elementów do tego ograniczonego zestawu było celowe, aby na początku zachować prostotę. W przyszłości, gdy przeprowadzimy więcej badań, możemy dodać dodatkowe elementy (np. pełną obsługę <svg>
).
Pomiary LCP uwzględniają tylko niektóre elementy, a poza tym używają heurystyki, aby wykluczać elementy, które użytkownicy prawdopodobnie uznają za „niezawierające treści”. W przypadku przeglądarek opartych na Chromium:
- Elementy o przezroczystości 0, które są niewidoczne dla użytkownika
- Elementy, które zajmują cały widoczny obszar i są raczej traktowane jako tło niż treść.
- obrazy zastępcze lub inne obrazy o niskiej entropii, które prawdopodobnie nie odzwierciedlają prawdziwej zawartości strony;
Przeglądarki będą prawdopodobnie nadal ulepszać te heurystyki, aby spełniać oczekiwania użytkowników dotyczące największego elementu zawierającego treści.
Te heurystyki dotyczące „treści” mogą się różnić od tych używanych przez pierwsze wyrenderowanie treści (FCP), które mogą uwzględniać niektóre z tych elementów, np. obrazy zastępcze lub obrazy w całym widocznym obszarze, nawet jeśli nie kwalifikują się jako kandydaci do LCP. Mimo że obie nazwy zawierają słowo „contentful”, mają one inny cel. FCP mierzy czas, w którym dowolne treści są renderowane na ekranie, a LCP – gdy renderowane są treści główne. Wskaźnik LCP ma więc być bardziej selektywny.
Jak określa się rozmiar elementu?
Rozmiar elementu zgłaszany w przypadku LCP to zwykle rozmiar widoczny dla użytkownika w widocznym obszarze. Jeśli element wykracza poza widoczny obszar, jeśli część elementu jest przycięta lub jeśli element ma niewidoczny przepełnienie, te części nie są wliczane do rozmiaru elementu.
W przypadku elementów obrazu, których rozmiar został zmieniony względem właściwego rozmiaru, rozmiar, który jest zgłaszany, to widoczny rozmiar lub właściwy rozmiar, zależnie od tego, który z nich jest mniejszy.
W przypadku elementów tekstowych LCP uwzględnia tylko najmniejszy prostokąt, który może zawierać wszystkie węzły tekstowe.
W przypadku wszystkich elementów LCP nie uwzględnia marginesów, wypełnień ani obramowań zastosowanych za pomocą kodu CSS.
Kiedy jest raportowany LCP?
Strony internetowe często wczytują się etapami, dlatego największy element na stronie może się zmienić.
Aby obsłużyć tę potencjalną zmianę, przeglądarka wysyła PerformanceEntry
typu largest-contentful-paint
, który identyfikuje największy element treści, gdy tylko przeglądarka wyrenderuje pierwszy kadr. Jednak po renderowaniu kolejnych klatek będzie wysyłać kolejną wartość PerformanceEntry
za każdym razem, gdy zmieni się największy element treści.
Na przykład na stronie z tekstem i dużą grafiką przeglądarka może najpierw tylko wyrenderować tekst. W tym momencie wysyła ona wpis largest-contentful-paint
, którego właściwość element
odwołuje się prawdopodobnie do elementu <p>
lub <h1>
. Później, gdy obraz nagłówka zostanie załadowany, zostanie wysłany drugi wpis largest-contentful-paint
, a jego właściwość element
będzie się odwoływać do <img>
.
Element może być uznany za największy element treści tylko po wyrenderowaniu i wyświetleniu go użytkownikowi. Obrazy, które nie zostały jeszcze załadowane, nie są uważane za „renderowane”. Nie są to też węzły tekstowe, które używają czcionek internetowych w okresie blokowania czcionek. W takich przypadkach mniejszy element może zostać zgłoszony jako największy element z treścią, ale gdy tylko większy element zostanie wyrenderowany, zostanie utworzony kolejny element PerformanceEntry
.
Oprócz ładowania obrazów i czcionek z opóźnieniem strona może dodawać do DOM nowe elementy, gdy staje się dostępna nowa treść. Jeśli którykolwiek z tych nowych elementów jest większy niż poprzedni największy element zawierający treści, zostanie również zgłoszony nowy PerformanceEntry
.
Jeśli największy element treści zostanie usunięty z widocznego obszaru lub nawet z DOM, pozostanie największym elementem treści, dopóki nie zostanie wyrenderowany większy element.
Przeglądarka przestanie rejestrować nowe wpisy, gdy użytkownik wejdzie w interakcję ze stroną (kliknie ją, przewinie lub naciśnie klawisz), ponieważ interakcja użytkownika często zmienia to, co jest widoczne dla użytkownika (szczególnie w przypadku przewijania).
Na potrzeby analizy do usługi analitycznej należy przesyłać tylko ostatnio wysłane PerformanceEntry
.
Czas wczytywania a czas renderowania
Ze względów bezpieczeństwa sygnatura czasowa renderowania obrazów nie była pierwotnie udostępniana w przypadku obrazów z różnych źródeł, które nie mają nagłówka Timing-Allow-Origin
. Zamiast tego był widoczny tylko czas ich wczytywania (ponieważ jest on już dostępny w ramach wielu innych interfejsów API).
Może to doprowadzić do pozornie niemożliwej sytuacji, w której interfejsy API internetowe zgłaszają LCP jako wcześniejsze niż FCP. Nie jest to prawda, ale tak się dzieje z powodu tego ograniczenia bezpieczeństwa.
Ten problem został rozwiązany pod koniec 2024 r., a w Chrome 133 czas renderowania jest nieco dłuższy, nawet jeśli nie podano wartości Timing-Allow-Origin
.
Zalecamy jednak, aby w miarę możliwości ustawić nagłówek Timing-Allow-Origin
, ponieważ dzięki temu dane będą dokładniejsze, zwłaszcza w przypadku przeglądarek, które nie uwzględniają tej ostatniej zmiany.
Jak są obsługiwane zmiany układu i rozmiaru elementów?
Aby zminimalizować obciążenie związane z obliczaniem i przesyłaniem nowych wpisów dotyczących wydajności, zmiany rozmiaru lub położenia elementu nie powodują generowania nowych kandydatów do LCP. Uwzględniany jest tylko początkowy rozmiar i pozycja elementu w widocznym obszarze.
Oznacza to, że obrazy, które są początkowo renderowane poza ekranem, a potem przechodzą na ekran, mogą nie zostać uwzględnione w raportach. Oznacza to też, że elementy początkowo renderowane w widocznym obszarze, które następnie zostaną przesunięte w dół, poza widok, będą nadal raportować swój początkowy rozmiar w widocznym obszarze.
Przykłady
Oto kilka przykładów sytuacji, w których Largest Contentful Paint występuje w kilku popularnych witrynach:
Na obu osi czasu powyżej największy element zmienia się w miarę wczytywania treści. W pierwszym przykładzie do DOM-u dodano nowe treści, co zmienia element, który jest największy. W drugim przykładzie układ się zmienia, a treści, które były wcześniej największe, są usuwane z widocznego obszaru.
Chociaż często zdarza się, że wczytywane później treści są większe niż te, które już są na stronie, nie zawsze tak jest. W następnych 2 przykladach LCP występuje przed pełnym załadowaniem strony.
W pierwszym przykładzie logo Instagrama jest ładowane stosunkowo wcześnie i pozostanie największym elementem nawet wtedy, gdy inne treści będą stopniowo wyświetlane. W przykładzie strony z wynikami wyszukiwania Google największym elementem jest akapit tekstu, który wyświetla się, zanim wczytanie obrazów lub logo zostanie ukończone. Ponieważ wszystkie poszczególne obrazy są mniejsze niż ten akapit, pozostaje on największym elementem w trakcie wczytywania.
Jak mierzyć LCP
LCP można mierzyć w laboratorium lub w warunkach rzeczywistych. Jest on dostępny w tych narzędziach:
Narzędzia w polu
- Raport na temat użytkowania Chrome
- PageSpeed Insights
- Search Console (raport Core Web Vitals)
web-vitals
Biblioteka JavaScript
Narzędzia laboratoryjne
Pomiar LCP w JavaScript
Aby mierzyć LCP w JavaScript, możesz użyć interfejsu API Largest Contentful Paint. Ten przykład pokazuje, jak utworzyć regułę PerformanceObserver
, która nasłuchuje wpisów largest-contentful-paint
i zapisują je w konsoli.
new PerformanceObserver((entryList) => {
for (const entry of entryList.getEntries()) {
console.log('LCP candidate:', entry.startTime, entry);
}
}).observe({type: 'largest-contentful-paint', buffered: true});
W tym przykładzie każdy zarejestrowany wpis largest-contentful-paint
reprezentuje bieżącego kandydata do LCP. Zazwyczaj wartość startTime
ostatniego wyemitowanego wpisu to wartość LCP, ale nie zawsze tak jest. Nie wszystkie wpisy largest-contentful-paint
są odpowiednie do pomiaru LCP.
W następującej sekcji opisano różnice między tym, co raportuje interfejs API, a sposobem obliczania danych.
Różnice między danymi a interfejsem API
- Interfejs API wyśle rekordy
largest-contentful-paint
dla stron wczytywanych na karcie w tle, ale te strony powinny być ignorowane podczas obliczania LCP. - Po przełączeniu strony na tło interfejs API będzie nadal wysyłać wpisy
largest-contentful-paint
, ale te wpisy powinny być ignorowane podczas obliczania LCP (elementy mogą być brane pod uwagę tylko wtedy, gdy strona była cały czas na pierwszym planie). - Interfejs API nie przekazuje rekordów
largest-contentful-paint
, gdy strona jest przywracana z bufora wstecznego/do przodu, ale w takich przypadkach należy mierzyć LCP, ponieważ użytkownicy traktują te zdarzenia jako oddzielne wizyty na stronie. - Interfejs API nie uwzględnia elementów w ramkach iframe, ale dane tak, ponieważ są one częścią wrażeń użytkownika. Na stronach, na których element LCP znajduje się w elemencie iframe (np. obraz plakatu w osadzonym filmie), będzie to widoczne jako różnica między CrUX a RUM. Aby prawidłowo mierzyć LCP, weź je pod uwagę. Ramki podrzędne mogą używać interfejsu API do raportowania swoich wpisów
largest-contentful-paint
do ramki nadrzędnej w celu ich agregacji. - Interfejs API mierzy LCP od momentu rozpoczęcia nawigacji, ale w przypadku stron z renderowaniem wstępnym czas LCP powinien być mierzony od
activationStart
, ponieważ odpowiada on temu, jak długo użytkownik odczuwa czas LCP.
Zamiast zapamiętywać te subtelne różnice, programiści mogą używać web-vitals
biblioteki JavaScriptu do pomiaru LCP, która załatwia te różnice (w miarę możliwości – zwróć uwagę, że problem z iframem nie jest uwzględniany):
import {onLCP} from 'web-vitals';
// Measure and log LCP as soon as it's available.
onLCP(console.log);
Pełny przykład pomiaru LCP w JavaScript znajdziesz w źródłowym kodzie onLCP()
.
Co zrobić, jeśli największy element nie jest najważniejszy?
W niektórych przypadkach najważniejszy element (lub elementy) na stronie nie jest tym samym co największy element, a deweloperzy mogą być bardziej zainteresowani pomiarem czasu renderowania tych innych elementów. Jest to możliwe dzięki interfejsowi Element Timing API, zgodnie z opisem w artykule o wskaźnikach niestandardowych.
Jak poprawić LCP
Pełny przewodnik dotyczący optymalizacji LCP pomoże Ci w określaniu wartości LCP w warunkach rzeczywistych i w optymalizacji tych wartości za pomocą danych z laboratorium.
Dodatkowe materiały
- Lessons learned from performance monitoring in Chrome (na podstawie artykułu Annie Sullivan z performance.now()) (2019 r.)
Historia zmian
Czasami w interfejsach API służących do pomiaru danych i czasami w definicjach samych danych występują błędy. W związku z tym czasami trzeba wprowadzić zmiany, które mogą się pojawiać w raportach i panelach jako ulepszenia lub regresje.
Aby ułatwić Ci zarządzanie tymi danymi, wszystkie zmiany w ich implementacji lub definicji będą widoczne w historii zmian.
Jeśli masz opinię na temat tych danych, możesz ją przekazać w grupie Google nt. opinii na temat funkcji web-vitals.