Core Web Vitals w praktyce
Core Web Vitals to trzy wskaźniki opisujące realne doświadczenie użytkownika w trzech obszarach:
- LCP — Largest Contentful Paint: jak szybko pojawia się główna treść,
- INP — Interaction to Next Paint: jak szybko interfejs reaguje na działania użytkownika,
- CLS — Cumulative Layout Shift: jak stabilny wizualnie jest layout.
Aktualne progi dobrego wyniku to:
| Metryka | Dobry wynik | Wymaga poprawy | Słaby wynik | | --- | --- | --- | --- | | LCP | ≤ 2,5 s | 2,5–4,0 s | > 4,0 s | | INP | ≤ 200 ms | 200–500 ms | > 500 ms | | CLS | ≤ 0,1 | 0,1–0,25 | > 0,25 |
Ocena Core Web Vitals w danych terenowych opiera się na 75. percentylu doświadczeń użytkowników, osobno dla urządzeń mobilnych i desktopowych.
To ważne, ponieważ pojedynczy szybki test na laptopie dewelopera nie mówi jeszcze, jak stronę odczuwają prawdziwi użytkownicy.
Dane laboratoryjne i dane rzeczywistych użytkowników
Przy analizie wydajności trzeba rozdzielić dwa rodzaje danych.
Lab data
Dane laboratoryjne powstają podczas kontrolowanego testu.
Przykłady:
- Chrome DevTools Performance,
- Lighthouse,
- lokalny profil CPU,
- test z throttlingiem sieci.
Ich zaletą jest powtarzalność. Można wykonać zmianę w kodzie i natychmiast sprawdzić, czy trace wygląda lepiej.
Field data
Field data pochodzi od realnych użytkowników.
Przykłady:
- Chrome UX Report — CrUX,
- PageSpeed Insights — część z danymi użytkowników,
- Search Console Core Web Vitals,
- własny Real User Monitoring wykorzystujący bibliotekę
web-vitals.
CrUX wykorzystuje 28-dniowe okno danych. Dlatego poprawka wdrożona dzisiaj nie sprawi, że jutro wszystkie raporty terenowe pokażą nowy wynik.
Najlepszy workflow to:
field data → reprodukcja problemu → DevTools → poprawka → test lokalny → deployment → ponowna obserwacja field data
Jak otworzyć Core Web Vitals w Chrome DevTools
W aktualnym Chrome najwygodniej zacząć od panelu Performance.
- Otwórz badaną stronę.
- Otwórz DevTools.
- Przejdź do zakładki Performance.
- Zobacz sekcję Live Metrics.
- Przeładuj stronę, jeśli analizujesz LCP.
- Klikaj, otwieraj menu, wpisuj tekst i wykonuj typowe akcje, jeśli analizujesz INP.
- Obserwuj layout podczas ładowania i dynamicznych zmian, jeśli analizujesz CLS.
Live Metrics pokazują LCP, CLS oraz — po wykonaniu interakcji — INP.
To dobry pierwszy krok, ale nie końcowa diagnoza.
Jeżeli widzisz problem, nagraj performance trace i sprawdź, co dokładnie wydarzyło się na main threadzie, w sieci i podczas renderowania.
LCP — co naprawdę mierzy Largest Contentful Paint
LCP mierzy czas do wyrenderowania największego istotnego elementu treści widocznego w początkowym viewportcie.
Często jest to:
- obraz hero,
- duży baner,
- główny nagłówek,
- duży blok tekstu,
- poster wideo.
Nie pytamy więc: „kiedy strona skończyła się ładować?”.
Pytamy:
kiedy użytkownik zobaczył główną treść, dla której przyszedł na stronę?
Dobry LCP to maksymalnie 2,5 sekundy.
Jak znaleźć element LCP w Chrome
W Performance → Live Metrics Chrome może wskazać aktualny element LCP.
Po nagraniu trace LCP jest również zaznaczony na osi czasu.
Kliknięcie zdarzenia pozwala przejść do szczegółów i odpowiedzieć na pierwsze pytanie:
co właściwie jest naszym LCP?
Jeżeli LCP jest dużym obrazem hero, optymalizowanie komponentu stopki niczego nie zmieni.
Jeżeli LCP jest tekstem, problem może wynikać z fontu, render-blocking CSS, TTFB albo kodu opóźniającego renderowanie.
Cztery części LCP
Dla zasobu takiego jak obraz LCP można rozbić na kilka etapów:
- TTFB — czas do pierwszego bajtu dokumentu.
- Resource load delay — czas od TTFB do rozpoczęcia pobierania zasobu LCP.
- Resource load duration — samo pobieranie zasobu.
- Element render delay — czas od zakończenia pobierania do faktycznego wyrenderowania elementu.
To rozbicie jest dużo bardziej użyteczne niż samo stwierdzenie „LCP = 4,2 s”.
Wysoki TTFB
Sprawdź backend, SSR, bazę danych, zewnętrzne API, cache, CDN, geografię serwera i middleware.
Wysoki resource load delay
Przeglądarka za późno odkrywa zasób.
Typowe przyczyny:
- obraz pojawia się dopiero po wykonaniu JavaScriptu,
- lazy loading na obrazie hero,
- źle ustawiony preload lub priorytet pobierania,
- klient musi poczekać na hydration.
Długi resource load duration
Sam zasób jest ciężki albo wolno dostarczany.
Sprawdź format obrazu, rozdzielczość, srcset, kompresję, CDN i cache headers.
Wysoki render delay
Zasób jest już pobrany, ale browser nadal go nie pokazuje.
Możliwe przyczyny:
- długi JavaScript,
- hydration,
- render-blocking CSS,
- font,
- ciężkie style,
- animacja wejścia opóźniająca widoczność.
Typowy błąd: lazy loading obrazu LCP
Obraz znajdujący się na pierwszym ekranie zwykle nie powinien być traktowany jak content znajdujący się daleko poniżej folda.
Jeżeli najważniejszy obraz ma:
<img loading="lazy" ... />
przeglądarka może rozpocząć jego pobieranie później, niż powinna.
W Next.js należy świadomie ustawić priorytet pobierania dla obrazu będącego kandydatem LCP zamiast bezrefleksyjnie lazy-loadować wszystkie obrazy.
Nie oznacza to, że wszystkie obrazy powinny mieć wysoki priorytet. Priorytet ma dostać niewielka liczba zasobów naprawdę krytycznych.
INP — responsywność całej wizyty
INP zastąpił FID jako Core Web Vital odpowiedzialny za responsywność.
FID patrzył tylko na pierwszą interakcję. INP obserwuje interakcje podczas całej wizyty użytkownika i wybiera reprezentatywnie najgorszą z nich, z ograniczeniem wpływu skrajnych wartości przy bardzo dużej liczbie interakcji.
Dobry wynik INP to maksymalnie 200 ms.
INP dotyczy interakcji takich jak:
- kliknięcie,
- tapnięcie,
- użycie klawiatury.
Nie jest metryką czasu pobierania requestu do API. Mierzy czas od działania użytkownika do kolejnego wyrenderowania obrazu, który pokazuje rezultat tej interakcji.
Z czego składa się wolna interakcja
Interakcję można podzielić na trzy części:
- Input delay — użytkownik wykonał akcję, ale event handler jeszcze nie ruszył.
- Processing duration — działa kod obsługi zdarzenia.
- Presentation delay — kod się skończył, ale browser musi jeszcze policzyć style, layout, paint i pokazać kolejną klatkę.
Wysoki input delay
Main thread był już zajęty.
Szukaj:
- long tasks,
- dużych bundle JS,
- kosztownej hydracji,
- timerów,
- kodu third-party,
- renderów wykonywanych w złym momencie.
Wysoki processing duration
Event handler wykonuje zbyt dużo pracy.
Szukaj:
- ciężkich pętli,
- sortowania dużych kolekcji,
- parsowania dużego JSON,
- synchronicznych obliczeń,
- dużych rerenderów React/Vue,
- rozbudowanej logiki uruchamianej na każde kliknięcie lub
input.
Wysoki presentation delay
Kod zakończył pracę, ale render jest drogi.
Sprawdź:
- style recalculation,
- layout,
- duże drzewo DOM,
- wymuszony synchroniczny layout,
- kosztowny paint,
- rozbudowane efekty wizualne.
Jak diagnozować INP w Performance
Najpierw otwórz Live Metrics i wykonaj interakcję, która wydaje się wolna.
Może to być:
- otwarcie menu,
- dodanie produktu do koszyka,
- przełączenie taba,
- kliknięcie filtra,
- wpisywanie w wyszukiwarkę,
- otwarcie modala.
Jeśli Chrome pokaże słaby INP, nagraj trace i powtórz ten sam scenariusz.
Następnie sprawdź:
- Interactions,
- główny wątek,
- long tasks,
- call stack,
- style/layout/paint po handlerze.
Nie zaczynaj od losowego usuwania bibliotek.
Najpierw ustal, czy problemem jest oczekiwanie na main thread, kod handlera czy renderowanie następnej klatki.
Long tasks i blokowanie main threada
Przy INP bardzo często problemem są długie zadania JavaScript.
Jeżeli main thread wykonuje jedno zadanie przez setki milisekund, użytkownik może kliknąć przycisk, ale handler nie zostanie uruchomiony od razu.
Typowe rozwiązania:
- dzielenie pracy na mniejsze zadania,
- lazy loading kodu,
- code splitting,
- ograniczanie third-party JS,
- unikanie ciężkich obliczeń w handlerze,
- przenoszenie odpowiednich obliczeń do Web Worker,
- redukcja zbędnych rerenderów,
- świadome yieldowanie do main threada przy długiej pracy.
CLS — stabilność layoutu
CLS mierzy niespodziewane przesunięcia elementów strony.
Klasyczny przykład:
- użytkownik zaczyna czytać artykuł,
- nad tekstem ładuje się obraz bez zarezerwowanego miejsca,
- cały tekst przesuwa się w dół.
Albo:
- użytkownik chce kliknąć przycisk,
- pojawia się banner,
- przycisk przesuwa się,
- użytkownik klika coś innego.
Dobry CLS to maksymalnie 0,1.
CLS nie jest mierzony w sekundach. To bezwymiarowy wynik wynikający ze skali i zasięgu przesunięć layoutu.
Jak znaleźć źródło CLS w Chrome
Performance → Live Metrics pokazuje historię layout shifts.
W trace zobaczysz zdarzenia związane z przesunięciami.
Kliknięcie konkretnego zdarzenia pozwala ustalić:
- które elementy się przesunęły,
- jak duży był shift,
- co wydarzyło się tuż przed nim.
CLS = 0,18 może wynikać z jednego dużego błędu albo z wielu małych przesunięć.
Najczęstsze przyczyny CLS
Obrazy bez wymiarów
Browser nie zna wcześniej miejsca potrzebnego na obraz.
Używaj width i height, aspect-ratio albo komponentów obrazowych rezerwujących przestrzeń.
Dynamiczna treść wstawiana nad istniejącą
Baner, alert, reklama albo komunikat nie powinny niespodziewanie spychać treści, którą użytkownik już widzi.
Fonty
Zmiana z fallback fontu na font docelowy może zmienić szerokość i wysokość tekstu.
Pomagają właściwa strategia ładowania fontów, dobrze dobrany fallback i — w bardziej wymagających przypadkach — font metric overrides.
Animowanie właściwości wpływających na layout
Jeżeli efekt na to pozwala, często lepiej użyć transform i opacity niż animować właściwości wymuszające layout.
Performance panel — workflow krok po kroku
1. Otwórz stronę w Incognito
Rozszerzenia mogą wykonywać własny JavaScript i zanieczyszczać profil.
2. Ustal scenariusz
Nie mierz „strony”. Mierz konkretny przypadek:
- pierwsze wejście na stronę produktu,
- otwarcie menu,
- filtrowanie wyników,
- przejście do checkoutu.
3. Ustaw środowisko
Jeżeli problem dotyczy użytkowników mobilnych, test na szybkim desktopie bez throttlingu może go ukryć.
4. Sprawdź Live Metrics
Zobacz LCP, CLS i INP.
5. Nagraj trace
Uruchom nagrywanie, wykonaj scenariusz i zatrzymaj trace.
6. Zacznij od znacznika problemu
Dla LCP kliknij LCP. Dla INP znajdź problematyczną interakcję. Dla CLS znajdź layout shift.
7. Idź wstecz do przyczyny
Dopiero teraz analizuj Network, Main, Call tree, Bottom-up, Layout, Paint i Insights.
Network i Core Web Vitals
Panel Performance nie zastępuje Network.
Przy LCP warto sprawdzić:
- kiedy request został odkryty,
- jego priorytet,
- TTFB,
- rozmiar,
- cache,
- redirecty,
- zależności od innych zasobów.
Jeżeli request obrazu hero zaczyna się dopiero po kilku sekundach, sam WebP nie rozwiąże problemu.
Często ważniejsze jest wcześniejsze odkrycie zasobu niż dalsze obcinanie kilku kilobajtów.
Lighthouse a Performance — kiedy używać którego
Lighthouse jest dobry do szybkiego, powtarzalnego audytu i znalezienia klasy problemu.
Performance jest lepszy, gdy trzeba odpowiedzieć: „dlaczego ten konkretny LCP lub klik trwa tak długo?”.
Lighthouse może powiedzieć:
- ogranicz JavaScript,
- popraw LCP,
- usuń render-blocking resources.
Performance pozwala zobaczyć konkretny request, task, event handler i moment renderowania.
PageSpeed Insights a Chrome DevTools
PageSpeed Insights może pokazać dwa różne obrazy tej samej strony.
Dane użytkowników
Jeżeli URL lub origin ma wystarczająco danych w CrUX, zobaczysz wyniki realnych użytkowników z ostatniego 28-dniowego okna.
Lighthouse
Niżej pojawia się test laboratoryjny.
Możliwe więc, że Lighthouse jest zielony, a field data nadal jest czerwone — albo odwrotnie.
To nie musi być błąd.
Dlaczego dobry Lighthouse nie gwarantuje dobrego INP
Lighthouse wykonuje kontrolowany scenariusz.
INP jest metryką całej wizyty i zależy od rzeczywistych interakcji.
Strona może ładować się świetnie, ale mieć bardzo wolny autocomplete, filtr, modal, koszyk, formularz albo menu.
Dlatego INP wymaga interakcji albo real-user monitoring.
Jak poprawiać LCP
Najczęstsze kierunki:
- popraw TTFB,
- cache SSR,
- użyj CDN,
- zoptymalizuj obraz LCP,
- pozwól browserowi wcześnie odkryć obraz,
- nie lazy-loaduj krytycznego hero,
- ogranicz render-blocking resources,
- zmniejsz JavaScript wymagany do pierwszego renderu,
- unikaj opóźniania widoczności hero animacją,
- zoptymalizuj fonty.
Nie wdrażaj wszystkich punktów w ciemno. Najpierw sprawdź breakdown konkretnego LCP.
Jak poprawiać INP
Najczęstsze kierunki:
- ogranicz long tasks,
- podziel ciężkie zadania,
- zmniejsz koszt event handlerów,
- ogranicz synchroniczny JavaScript,
- zoptymalizuj rerendery,
- zmniejsz DOM,
- ogranicz third-party scripts,
- odłóż pracę niepotrzebną do obsługi bieżącej interakcji,
- użyj Web Worker dla odpowiednich obliczeń,
- sprawdź koszt layoutu i paint po interakcji.
INP nie jest problemem „frameworka”. Można mieć szybki React i wolny vanilla JS — oraz odwrotnie.
Jak poprawiać CLS
Najczęstsze kierunki:
- rezerwuj miejsce na obrazy i multimedia,
- nie wstawiaj dynamicznej treści nad aktualnym viewportem,
- stabilizuj wysokości komponentów asynchronicznych,
- kontroluj zachowanie fontów,
- unikaj layoutowych animacji,
- sprawdzaj bannery consent i komunikaty,
- rezerwuj miejsce na widgety third-party.
CLS często da się naprawić bez wielkiego refactoru aplikacji.
Jak mierzyć po wdrożeniu
Po optymalizacji wykonaj ten sam scenariusz laboratoryjny.
Porównaj trace przed i po, LCP, czas long tasków, koszt interakcji i layout shifts.
Następnie obserwuj dane realnych użytkowników.
Pamiętaj, że CrUX jest 28-dniowym rolling window. Wynik terenowy będzie zmieniał się stopniowo.
Jeżeli wydajność jest krytyczna biznesowo, warto wdrożyć własny RUM i zbierać Web Vitals razem z kontekstem, na przykład URL-em, typem urządzenia, wersją aplikacji i identyfikatorem deploymentu.
Core Web Vitals i SEO
Core Web Vitals są elementem szerzej rozumianego page experience.
Nie należy traktować ich jak prostego wzoru:
lepszy LCP = automatycznie wyższa pozycja
Google nadal przede wszystkim próbuje wyświetlać najbardziej użyteczną i trafną treść. Dobra jakość strony może pomagać, szczególnie gdy wiele wyników odpowiada na zapytanie równie dobrze.
Core Web Vitals mają jednak wartość nawet wtedy, gdy całkowicie pominiemy SEO.
Szybkie ładowanie, responsywne interakcje i stabilny layout po prostu tworzą lepszy produkt.
Checklista audytu Core Web Vitals
- Sprawdziliśmy dane CrUX, jeśli są dostępne.
- Rozdzieliliśmy mobile i desktop.
- Wiemy, który element jest LCP.
- Sprawdziliśmy breakdown LCP.
- Wiemy, kiedy browser odkrywa zasób LCP.
- Sprawdziliśmy TTFB.
- Wykonaliśmy realne interakcje i zmierzyliśmy INP.
- Zidentyfikowaliśmy input delay, processing i presentation delay.
- Sprawdziliśmy long tasks na main threadzie.
- Zidentyfikowaliśmy źródła layout shifts.
- Sprawdziliśmy obrazy bez zarezerwowanych wymiarów.
- Sprawdziliśmy fonty i dynamiczne komponenty.
- Porównaliśmy Lighthouse z field data.
- Testowaliśmy na słabszym CPU i sieci.
- Powtórzyliśmy identyczny scenariusz po zmianach.
- Po wdrożeniu obserwujemy dane realnych użytkowników.
Podsumowanie
Core Web Vitals nie są trzema liczbami do „wyzerowania w Lighthouse”.
LCP odpowiada na pytanie, kiedy użytkownik widzi główną treść. INP pokazuje, czy interfejs reaguje bez irytującego opóźnienia. CLS mówi, czy strona pozostaje stabilna podczas używania.
Chrome DevTools pozwala przejść od wyniku do konkretnej przyczyny: requestu, long taska, event handlera, layoutu albo paintu.
Najskuteczniejszy proces nie zaczyna się więc od listy przypadkowych optymalizacji. Zaczyna się od pomiaru realnego problemu, nagrania reprezentatywnego scenariusza i znalezienia najdroższego fragmentu ścieżki.
Najpierw dane. Potem hipoteza. Potem poprawka. Na końcu ponowny pomiar.
Źródła techniczne
- Web Vitals: https://web.dev/articles/vitals
- Chrome DevTools Performance: https://developer.chrome.com/docs/devtools/performance
- Performance reference: https://developer.chrome.com/docs/devtools/performance/reference
- Google Search Central — Core Web Vitals: https://developers.google.com/search/docs/appearance/core-web-vitals
- Chrome UX Report methodology: https://developer.chrome.com/docs/crux/methodology/tools
Modernizacja aplikacji