Uruchomiłem Lighthouse 28 razy dla czterech adresów CometWeb, nie zmieniając w międzyczasie kodu. Oceny wahały się od 63 do 77 punktów. PageSpeed Insights pokazywał inne wyniki, a dla tych stron nie miałem dostępnych danych terenowych CrUX.
Rozbieżności nie oznaczają automatycznie błędu któregoś z narzędzi. Lighthouse opisuje pojedynczy test w określonych warunkach, a CrUX zbiera statystyki rzeczywistych wizyt użytkowników Chrome, o ile danych jest wystarczająco dużo. Zestawienie obu źródeł pozwala oddzielić szukanie przyczyn od oceny doświadczeń rzeczywistych użytkowników.
Najważniejsze wyniki - LCP strony /pricing rozjechał się w siedmiu identycznych próbach o 2,1 s. - PageSpeed Insights ocenił te same URL-e o 4 do 18 punktów wyżej niż lokalny Lighthouse 13.5.0. - W pięciu publicznych serwisach z danymi CrUX laboratoryjny LCP był od 1,06 do 2,18 raza wyższy niż p75 w terenie. - developer.chrome.com dostał w laboratorium 77 punktów, a w terenie miał INP 294 ms przy progu 200 ms.
Dane laboratoryjne, CrUX i RUM odpowiadają na trzy różne pytania
Dane laboratoryjne pochodzą z testu w określonych warunkach urządzenia i sieci. CrUX zbiera zagregowane pomiary wizyt użytkowników Chrome, a własny RUM pozwala prowadzić pomiary w swoim serwisie.
Według przeglądu Web Vitals na web.dev Core Web Vitals to przede wszystkim metryki terenowe, choć większość z nich da się zmierzyć także w laboratorium.
Progi są trzy: LCP do 2,5 s, INP (czas reakcji na kliknięcie lub klawisz) do 200 ms i CLS (przesunięcia układu strony) do 0,1, liczone przy 75. percentylu wczytań, osobno dla telefonów i komputerów. Strona zalicza ocenę, gdy przy tym percentylu spełnia wszystkie trzy.
Ocenę daje więc teren, bo laboratoryjny LCP 6 s to czas jednego symulowanego testu, a użytkownicy mogą czekać krócej. Laboratoryjny LCP 1,5 s z tego samego powodu też niczego nie zalicza.
Jak to zmierzyłem
Wziąłem cztery strony produkcyjne: /, /pricing, /tools/auditor i angielską wersję artykułu o WOFF2 (/blog/woff2-vs-ttf), bez logowania i bez zgody na cookies. Każdą przepuściłem 7 razy przez Lighthouse 13.5.0 z domyślnym profilem mobilnym, w wersji, którą tego dnia raportował PageSpeed Insights.
Lighthouse działał w Chromium z Playwrighta, z nowym profilem przy każdej próbie, więc każde ładowanie było zimne, a próby szły na zmianę między stronami. Do tego 3 wywołania API PageSpeed Insights na stronę i dane CrUX, które PSI dołącza do odpowiedzi.
Łączna waga każdej strony mieściła się między próbami w 0,31 KB. Główne ograniczenie to jeden komputer i jeden dzień, 24 września 2026. Skrypty, wszystkie próby i podsumowanie, z którego pochodzi każda liczba, są w pakiecie badań.
Ta sama strona w siedmiu próbach: LCP różnił się o 2,1 s
Mediana wszystkich 28 prób to 69 punktów, a każda strona rozjeżdżała się w swoich siedmiu próbach o 4 do 10 punktów.
| Strona | Wynik, mediana (min–maks) | LCP lab, mediana (min–maks) | TBT, mediana (min–maks) | CLS |
|---|---|---|---|---|
/ | 67 (63–68) | 6,4 s (6,0–6,8) | 32 ms (17–43) | 0 w każdej próbie |
/pricing | 67 (65–75) | 6,3 s (4,9–7,0) | 3 ms (0–17) | 0 w każdej próbie |
/tools/auditor | 69 (68–72) | 5,9 s (5,3–6,1) | 1 ms (0–31) | 0 w każdej próbie |
/blog/woff2-vs-ttf | 70 (69–77) | 5,7 s (4,8–5,9) | 0 ms (0–20) | 0 w każdej próbie |
Największy rozrzut miała strona /pricing, gdzie laboratoryjny LCP wahał się od 4,9 do 7,0 s. To 33% względem mediany tej strony, a w kodzie nic się nie zmieniło.
Zespół Lighthouse opisuje to zjawisko w dokumentacji o zmienności wyników i radzi patrzeć na medianę, bo mediana z pięciu prób jest dwa razy stabilniejsza niż pojedynczy test.
Część rozbieżności wynika z działania symulacji. Domyślny profil mobilny używa symulowanego dławienia, opisanego w dokumentacji dławienia Lighthouse. Lighthouse ładuje stronę na prawdziwym łączu i modeluje, jak wyglądałoby ładowanie przy opóźnieniu 150 ms, przepustowości 1,6 Mb/s i czterokrotnie wolniejszym procesorze.
Obok metryk symulowanych raport zapisuje czasy prawdziwego ładowania bez dławienia („observed”), więc zapisałem oba zestawy.
Puste kółka na wykresie oznaczają rzeczywiste ładowania bez symulowanego ograniczenia parametrów sieci. Cztery najszybsze prawdziwe ładowania to dokładnie cztery najlepsze wyniki symulowane w tabeli: 75 na /pricing, 77 na artykule o WOFF2 i dwa razy 72 na /tools/auditor.
Symulacja liczy dławione ładowanie z niedławionego, więc każde wahanie prawdziwego ładowania przechodzi prosto do wyniku. Przy jednym teście przed zmianą i jednym po niej kilka punktów albo nawet 2 s LCP może być szumem, dlatego porównuję mediany z kilku prób.
PageSpeed Insights ocenił te same strony o 4–18 punktów wyżej
Mediana wyniku w PageSpeed Insights była wyższa niż lokalna dla każdego z czterech URL-i, o 4 do 18 punktów, a mediana laboratoryjnego LCP niższa o 1,6 do 2,6 s.
| Strona | Wynik PSI, mediana (min–maks) | Wynik lokalny, mediana | LCP lab PSI, mediana | LCP lab lokalnie, mediana |
|---|---|---|---|---|
/ | 71 (63–76) | 67 | 4,5 s | 6,4 s |
/pricing | 85 (79–85) | 67 | 3,8 s | 6,3 s |
/tools/auditor | 79 (78–82) | 69 | 4,2 s | 5,9 s |
/blog/woff2-vs-ttf | 78 (77–81) | 70 | 4,1 s | 5,7 s |
Wersja Lighthouse i profil były te same, a raporty pokazują dwie przyczyny różnicy.
Pierwsza przyczyna to wolniejszy procesor maszyn PSI, co widać w benchmark index, który Lighthouse zapisuje dla maszyny, na której działał. Mój komputer uzyskał od 4191 do 4430 w 28 próbach, a maszyny PSI od 499 do 1338.
Widać to było w Total Blocking Time, czyli czasie, w którym główny wątek blokuje reakcję strony. Jedna próba PSI strony głównej zapisała 433 ms, a moje lokalne maksimum wyniosło 43 ms.
Według opisu punktacji Lighthouse TBT waży 30% wyniku Performance od Lighthouse 10. Trzy wyniki PSI strony głównej wahały się od 63 do 76 razem z TBT (55–433 ms), choć LCP różnił się najwyżej o 150 ms.
Druga przyczyna to trasa sieciowa, bo PSI działa w centrum danych Google, jak podaje strona o PageSpeed Insights, a moje próby szły z domowego łącza w Polsce. Z tych danych nie rozdzielę różnicy LCP między te dwie przyczyny, więc nie będę zgadywał.
Porównuj więc wyniki laboratoryjne tylko z tego samego narzędzia, konfiguracji i rodzaju maszyny. Wynik PSI ze zrzutu ekranu klienta i wynik Lighthouse z twojego laptopa to dwa osobne pomiary, więc pary „przed i po” z nich nie złożysz.
CrUX: dane terenowe dla 0 z 4 stron cometweb.io
Każda odpowiedź PSI wróciła z pustą sekcją danych terenowych, bez danych dla URL-a i bez danych zastępczych dla całego originu cometweb.io. Pusta sekcja znaczy „za mało danych” i nie jest ani błędem, ani zerem.
Według dokumentacji PageSpeed Insights PSI pokazuje dane terenowe, gdy strona ma w CrUX wystarczająco wiele próbek. Gdy nie ma, przechodzi na dane originu, a gdy i origin ma ich za mało, nie pokazuje nic.
Żeby w ogóle trafić do zbioru, strona musi być publicznie wykrywalna i „wystarczająco popularna”, czyli mieć minimalną liczbę odwiedzających, której Chrome nie ujawnia.
Kwalifikować muszą się też użytkownicy: metodologia CrUX liczy tylko użytkowników Chrome z włączonym raportowaniem statystyk użytkowania i synchronizacją historii bez hasła synchronizacji. Chrome na iOS, Android WebView i inne przeglądarki oparte na Chromium, na przykład Edge, wypadają.
Raport Core Web Vitals w Search Console pokazuje wtedy komunikat „No data available” (pomoc Search Console), co przy małym ruchu jest wynikiem spodziewanym.
Co raportować, gdy brakuje danych terenowych:
Dane terenowe: N/D, brak danych CrUX dla URL-a i originu w PSI, stan na [data].Dane laboratoryjne: syntetyczne, mediana z [n] prób, [narzędzie, wersja, konfiguracja].Następny krok: zbierz własny RUM albo zachowaj bazę laboratoryjną i powtórz ją po zmianie.
Brak danych terenowych zostaw jako N/D, bo zero, domniemane zaliczenie albo „wynik użytkowników” wyliczony z laboratorium wprowadzą czytelnika raportu w błąd.
W 5 z 5 serwisów z danymi CrUX laboratoryjny LCP był wyższy niż teren
Tam, gdzie dane terenowe są, laboratorium mówiło co innego. Wywołałem PSI po razie dla stron głównych pięciu publicznych serwisów dokumentacyjnych, które najpewniej mają dane CrUX. Wszystkie pięć je miały, dla URL-a i w tej samej odpowiedzi co test laboratoryjny.
| Serwis | Wynik lab | LCP lab | LCP p75 w terenie | INP p75 w terenie | CLS p75 w terenie | Zalicza CWV w terenie? |
|---|---|---|---|---|---|---|
| web.dev | 44 | 6,8 s | 3,1 s | 220 ms | 0 | Nie (LCP, INP) |
| developer.chrome.com | 77 | 3,8 s | 3,0 s | 294 ms | 0,02 | Nie (LCP, INP) |
| developer.mozilla.org | 95 | 2,7 s | 1,9 s | 160 ms | 0,04 | Tak |
| www.w3.org | 100 | 1,7 s | 1,1 s | 89 ms | 0 | Tak |
| www.wikipedia.org | 100 | 1,4 s | 1,3 s | 98 ms | 0 | Tak |
- Laboratoryjny LCP był wyższy we wszystkich pięciu, od 1,06 raza na Wikipedii do 2,18 raza na web.dev. Według tekstu web.dev o różnicach między danymi laboratoryjnymi a terenowymi laboratorium ładuje stronę na zimno, na emulowanym telefonie średniej klasy i wolnym łączu, a prawdziwe wizyty mają cache, przywrócenia z back/forward cache i szybsze urządzenia. Jak duża bywa ta różnica zwykle, pięć serwisów nie powie.
- MDN miał w laboratorium LCP powyżej progu, a w terenie zalicza. Test pokazał 2,7 s, a użytkownicy Chrome mieli 1,9 s przy 75. percentylu. Strona zalicza w terenie wszystkie trzy Core Web Vitals.
- developer.chrome.com zrobił odwrotnie. Dostał w laboratorium 77 punktów, a w terenie oblewa LCP i INP, z INP 294 ms przy 75. percentylu. Tej wartości żaden test laboratoryjny by nie pokazał.
Zwykły test Lighthouse nie mierzy INP, a TBT jest wskazówką
INP mierzy reakcję strony na kliknięcie, dotknięcie albo klawisz, a Lighthouse ładuje stronę bez nikogo przy klawiaturze. Interakcję możesz zmierzyć w laboratorium sam, np. w DevTools albo w trybie timespan Lighthouse, ale wtedy mierzysz swoje kliknięcia, a nie ruch prawdziwych użytkowników.
W przeglądzie Web Vitals web.dev oznacza INP jako niemierzalny w Lighthouse i proponuje w zastępstwie Total Blocking Time, dodając, że lepszy TBT może poprawić INP w terenie. W raporcie TBT stoi więc w swoim polu, a pole INP zostaje dla danych terenowych.
Nasze strony miały medianę TBT od 0 do 32 ms lokalnie i od 19 do 248 ms na PSI. W teście nie było interakcji, więc te zakresy nic nie mówią o reakcji na otwarcie menu czy wpisanie adresu w audytorze.
developer.chrome.com miał 208 ms TBT w laboratorium i INP 294 ms w terenie, a web.dev 829 ms TBT i INP 220 ms, więc kierunek był podobny, ale skale zupełnie inne.
INP bierzesz z CrUX, jeśli strony się kwalifikują, albo z własnego RUM. Konkretną interakcję debugujesz w DevTools > Performance: nagrywasz ślad i wykonujesz ją sam. Szerzej piszę o tej metryce w haśle słownika o INP.
CLS równy 0 w 28 próbach opisuje tylko zimne ładowanie
Wszystkie 28 lokalnych prób naszych stron pokazało CLS równy dokładnie 0, a 12 prób PSI najwyżej 0,00003. Tyle że CLS w laboratorium obejmuje przesunięcia układu podczas samego ładowania.
W terenie liczy się całe życie strony, czyli też leniwie ładowane obrazy bez wymiarów, spóźnione treści personalizowane, reklamy i wszystko, co przesuwa się po interakcji. Opisuje to web.dev w tym samym tekście o różnicach lab i terenu.
Po ludzku: bez danych terenowych „CLS 0” znaczy „brak przesunięć podczas zimnego ładowania pierwszego ekranu”. Tylko tyle.
Laboratorium znalazło przyczynę wolnego LCP: logo czekało na JavaScript
Po 28 próbach uruchomiłem Lighthouse jeszcze raz na stronie głównej i przeczytałem diagnostykę zamiast wyniku (diagnostic-home.json), z której wyszły trzy tropy.
- Elementem LCP był tekst logo w nagłówku. W emulowanym widoku o szerokości 412 pikseli Lighthouse wybrał słowo „CometWeb” w pasku nawigacji, a nagłówek sekcji hero przegrał. Laboratorium raportuje zawsze ten sam element, a w terenie, jak zauważa web.dev, bywa on różny.
- Prawie cały zmierzony LCP to opóźnienie renderowania („element render delay”), czyli czas od pierwszego bajtu do pojawienia się tekstu.
- Sześć arkuszy CSS blokowało renderowanie. Lighthouse szacował ich koszt na około 580 ms na symulowanym łączu mobilnym, do tego 36 KiB nieużywanego CSS.
To stan sprzed poprawek, a oszczędności z listy to szacunki z jednej symulowanej próby. Sprawdziłem je pętlą z protokołu: jedna zmiana, siedem prób, porównanie median.
Najpierw poszedłem za tropem 3 i odroczyłem CSS, więc blokujących arkuszy zostały 3 z 6. FCP poprawił się o 0,12 s, a mediana LCP (6,34 s) została w starym zakresie, więc szacunek 580 ms okazał się za optymistyczny.
Hamulcem okazał się JavaScript, bo wspólny layout importował cały słownik haseł i tabelę meta wszystkich podstron, więc każda strona pobierała je przed pierwszym renderem. Po wycięciu tych danych JS przed pierwszym renderem spadł z 329 do 208 KB (gzip).
Po wdrożeniu obu zmian zmierzyłem stronę główną na produkcji tak samo jak wcześniej. LCP spadł z 6,39 do 5,46 s, FCP z 4,14 do 3,64 s, a wynik z 65 do 69. Tabela i surowe przebiegi są w pomiarze przed i po poprawce.
To przechodzi krok 6 protokołu, bo nowa mediana LCP jest niższa niż najszybsza z siedmiu prób przed poprawką (5,89 s). Pierwsza treść pojawia się o 0,50 s szybciej, a największy element pierwszego ekranu telefonu o 0,93 s, na razie w symulacji, bo danych terenowych dla tej strony dalej nie ma.
Protokół pomiaru Core Web Vitals odporny na szum, w 8 krokach
- Najpierw sprawdź dane terenowe. Zapisz datę i to, czy PSI pokazuje dane dla URL-a, originu, czy żadne. Przy obu źródłach priorytety według web.dev ustalają dane terenowe.
- Zapisz konfigurację laboratorium, czyli narzędzie i wersję, profil urządzenia, dławienie, stan cache i zgody, maszynę oraz benchmark index z każdego raportu.
- Wykonaj co najmniej pięć prób na wersję. Podawaj medianę i pełny zakres, nigdy najlepszą próbę.
- Czytaj diagnostykę obok wyniku, czyli element LCP, jego rozbicie na fazy, żądania blokujące renderowanie i długie zadania.
- Wdrażaj jedną skupioną zmianę, żeby porównanie dało się zinterpretować.
- Porównuj rozkłady. Uznaj zmianę za prawdziwą dopiero wtedy, gdy nowa mediana wychodzi poza zakres starej wersji w tej samej konfiguracji.
- Dane terenowe sprawdzaj w ich własnym rytmie. Według dokumentacji CrUX API CrUX to kroczące 28-dniowe agregaty aktualizowane codziennie. Przy każdej liczbie terenowej zapisuj okres zbierania danych.
- Gdy CrUX jest pusty, zbieraj własny RUM, czyli pomiar u prawdziwych odwiedzających. Najprościej biblioteką JavaScript web-vitals, co pokazuje poradnik web.dev o mierzeniu Web Vitals. Przed porównaniem z CrUX zawęź RUM do Chrome, bo według web.dev o różnicach między CrUX a RUM CrUX zawiera tylko Chrome i liczy przywrócenia z back/forward cache jako nawigacje. Więcej w haśle real-user monitoring.
Dla pojedynczego URL-a darmowy skan wydajności robi szybki test laboratoryjny i sprawdzenie HTTP. Same poprawki opisuję w poradniku 7 sposobów na przyspieszenie strony.
Przy kilkudziesięciu stronach ręczne powtarzanie tej pętli szybko się nudzi. Moduł Performance w CometWeb Insight oddziela CrUX od laboratorium i własnego wyniku syntetycznego, a gdy danych brakuje, podaje powód. Dla całej witryny wskazuje element, żądanie i kolejność napraw do porównania po wdrożeniu.
Na koniec: laboratorium do przyczyn, CrUX do oceny
Łatwa część to uruchomić Lighthouse, a trudna to wstrzymać się z wnioskiem po pierwszej liczbie.
Wyniki mają ograniczony zakres. Zaobserwowałem 14-punktowy rozrzut na czterech stronach niewielkiego serwisu, a dodatkowo sprawdziłem pięć znanych witryn. Nie rozstrzygają, jak cometweb.io odbierają prawdziwi ludzie, czy inne strony rozjadą się tak samo ani czy PSI zawsze ocenia wyżej.
Co zrobić jutro rano? Otwórz PageSpeed Insights dla swojej najważniejszej strony i zapisz, czy ma dane terenowe. Potem uruchom Lighthouse pięć razy i zapisz medianę z zakresem.
Tak powstaje twoja baza, a dla całej witryny naraz dostaniesz ją po założeniu konta w CometWeb Insight i pierwszym audycie. Potem zmieniasz jedną rzecz i mierzysz od nowa, tak samo jak za pierwszym razem.
Najczęstsze pytania
Czy Core Web Vitals wpływają na pozycję w Google?
Google Search Central zaleca dobre Core Web Vitals dla sukcesu w wyszukiwarce i opisuje je jako miary rzeczywistych doświadczeń użytkowników. Ani dobry wynik laboratoryjny, ani zaliczenie progów w terenie nie gwarantują pozycji. Liczą się też trafność, jakość treści, linki i indeksowanie.
Jak długo CrUX potrzebuje, żeby pokazać poprawkę?
Poprawka pojawia się w CrUX stopniowo, w miarę jak nowe wizyty zastępują starsze, a pełne okno wymienia się po 28 dniach. Do tego czasu p75 miesza wizyty sprzed zmiany i po niej. Do szybkiej informacji zwrotnej zachowaj laboratoryjną bazę z powtarzanych prób.
Gdzie zobaczę dane CrUX poza PageSpeed Insights?
Dane CrUX pokazuje też raport Core Web Vitals w Search Console, który korzysta z tych samych danych terenowych, oraz CrUX API. API wymaga klucza z włączonym dostępem do CrUX. W tym teście mój klucz go nie miał, dlatego brałem dane CrUX dołączone do odpowiedzi PSI.
Dlaczego mój RUM pokazuje inne liczby niż CrUX?
RUM i CrUX mierzą inne grupy wizyt w innych oknach. CrUX raportuje 75. percentyl z kroczących 28 dni, a twój RUM ma okres, który sam wybierzesz, i zwykle wszystkie przeglądarki, nie tylko Chrome. Przed porównaniem ustaw w RUM ten sam percentyl i to samo 28-dniowe okno.
Źródła i dane z testu
Pomiary nie są benchmarkiem, pomiarem terenowym cometweb.io ani prognozą dla innych stron.
Konfiguracja: Lighthouse 13.5.0 w Chrome for Testing 153 na Apple M5 Pro, API PageSpeed Insights v5, dane CrUX dołączone do odpowiedzi PSI. Serwisy zewnętrzne dostały po jednym wywołaniu PSI i nie były crawlowane.
Metodologia, Lokalne próby, Odpowiedzi PSI, Podsumowanie, Test diagnostyczny, Skrypt testów lokalnych, Skrypt PSI, Analiza, Wykresy, Pomiar przed i po poprawce
- web.dev: Web Vitals.
- web.dev: Why lab and field data can be different (and what to do about it).
- Google for Developers: About PageSpeed Insights.
- Chrome for Developers: CrUX methodology.
- Chrome for Developers: CrUX API.
- Dokumentacja Lighthouse: Score Variability.
- Dokumentacja Lighthouse: Network Throttling.
- Chrome for Developers: Lighthouse performance scoring.
- web.dev: Why is CrUX data different from my RUM data?
- web.dev: Getting started with measuring Web Vitals.
- Pomoc Search Console: Raport Core Web Vitals.
- Google Search Central: Understanding Core Web Vitals and Google search results.