Wszystkie posty
tools

Optymalizacja PageSpeed Insights: Core Web Vitals w praktyce

Jak poprawić wynik PageSpeed Insights i Core Web Vitals (LCP, INP, CLS): obrazy, fonty, JavaScript, budżet wydajności i Lighthouse CI. Sprawdzone techniki z realnych projektów i mierzalne efekty.

5 min czytaniaAktualizacja: 25 lipca 2026

Optymalizowałem wydajność stron o przeróżnym rodowodzie – od WordPressa z 30 pluginami po statyczne generatory. Za każdym razem ta sama historia: wynik PageSpeed Insights jest symptomem, a nie celem. Cel to szybkie pierwsze wrażenie dla realnego użytkownika na słabym telefonie. W tym poście pokazuję kompletny, praktyczny proces: co mierzyć, co optymalizować w kolejności wpływu i jak zamienić wynik w trwały budżet wydajności z Lighthouse CI.

Co faktycznie mierzy PageSpeed Insights

PageSpeed Insights łączy dwa źródła: dane laboratoryjne (Lighthouse na symulowanym słabym urządzeniu) i dane terenowe (CrUX – prawdziwi użytkownicy). Liczysz się z oboma. Rdzeniem są trzy metryki Core Web Vitals:

Metryka Co mierzy Dobry wynik Jak poprawić
LCP Czas załadowania największego elementu (zwykle obraz hero) < 2,5 s Obrazy, CDN, szybki TTFB
INP Reakcja na kliknięcia i interakcje < 200 ms Mały JS, długie zadania, brak render-blockingu
CLS Skoki układu podczas ładowania < 0,1 Atrybuty wymiarów, font-display, brak late-injected content

Kolejność pracy jest zawsze ta sama: zacznij od LCP (to najczęstszy problem), potem CLS (tani w naprawie), na końcu INP (najdroższy – wymaga myślenia o JS).

Pomiar: lab kontra field

Zanim cokolwiek zmienisz, zmierz dwukrotnie:

  1. PageSpeed Insights dla URL (5 pomiarów – wyniki w labie bywają rozrzucone),
  2. CrUX Dashboard (dane terenowe z ostatnich 28 dni) – to one decydują o tym, czy Google uzna stronę za “fast”,
  3. DevTools → Performance z throttlingiem 4G – do diagnozy, które zasoby blokują ścieżkę krytyczną.

Pamiętaj: wynik 100 przy LCP 4 s w danych terenowych to porażka. Liczy się doświadczenie użytkownika, nie kolor wskaźnika.

Obrazy: największa i najtańsza wygrana

Obrazy to zwykle 50-70% wagi strony. Kolejność działań:

  1. Format – WebP (a przy wsparciu AVIF) zamiast JPEG/PNG. Te same wymiary, ~30-50% mniejszy plik.
  2. Wymiary – wygeneruj warianty dla każdego breakpointa (srcset + sizes), nie skaluj 2000px obrazu do 400px w CSS.
  3. Lazy loading – obrazy poniżej linii cięcia dostają loading="lazy"; hero i LCP-element nigdy.
  4. fetchpriority="high" – na obraz hero, żeby przeglądarka zaczęła go pobierać natychmiast.
  5. CDN z obrazami – Cloudflare Images albo własna optymalizacja w buildzie (astro:assets, next/image robią to za Ciebie).

Przykładowy wynik z mojego projektu: 4,2 MB obrazów → 380 KB, LCP z 3,8 s na 1,2 s. Sam obraz hero robił 60% LCP.

Fonty: ciche zabójcy renderowania

Custom fonty to druga najczęstsza przyczyna wolnego LCP i dużego CLS. Dobre praktyki:

  • font-display: swap – tekst pojawia się natychmiast w fallbackowym foncie, a nie czeka na wczytanie. Brak tego atrybutu = niewidoczny tekst (FOIT) = zły LCP.
  • Preload tylko krytycznych fontów – preloaduj warianty używane w nagłówkach, nie wszystkie 8 grubości.
  • Subsetowanie – fonty wytnij do używanych znaków (polskie strony potrzebują łacińskiego rozszerzonego; nie ciągnij całych fontów CJK).
  • Self-host zamiast Google Fonts – jeden request do własnego origin, zero łączenia się z trzecią stroną. Przy statycznym generatorze fonty są wbudowane w CSS.
  • Ustal rozmiary w @font-facesize-adjust redukuje skok układu przy zamianie fontu fallbackowego na właściwy.

JavaScript: najmniejszy input, największy ból

INP psują przede wszystkim: za dużo JavaScriptu na starcie, długie zadania (> 50 ms) blokujące główny wątek i ciężkie biblioteki. Praktyczne techniki:

  • Mniej kodu – statyczny generator (Astro) renderuje HTML na serwerze i wysyła do klienta tylko interaktywne wyspy. Jeśli masz 200 KB JS na stronę z blogiem – masz za dużo.
  • Hydratacja na żądanie – komponenty interaktywne ładują się dopiero, gdy wchodzą w widok (client:visible), nie od razu.
  • Code splitting – ciężkie biblioteki (chart, editor) ładowane lazy, nigdy w głównym bundle.
  • Defer wszystko – skrypty bez defer/async blokują renderowanie. modulepreload zamiast preload dla modułów.
  • content-visibility: auto – sekcje poniżej linii cięcia renderują się dopiero przy scrollu.

Budżet wydajności: zamień wynik w regułę

Sam wynik to chwila; regresja wróci po następnym deployu. Dlatego każdy projekt dostaje budżet wydajności pilnowany w CI. Przykładowy plik budżetu (Lighthouse CI):

{
"ci": {
"collect": { "url": ["https://mahawir.pl/"], "numberOfRuns": 3 },
"assert": {
"assertions": {
"categories:performance": ["error", { "minScore": 0.9 }],
"categories:accessibility": ["error", { "minScore": 0.95 }],
"categories:seo": ["error", { "minScore": 0.95 }],
"lighthouse-core/audits/largest-contentful-paint": ["error", { "maxNumericValue": 2500 }],
"lighthouse-core/audits/cumulative-layout-shift": ["error", { "maxNumericValue": 0.1 }],
"lighthouse-core/audits/total-blocking-time": ["error", { "maxNumericValue": 200 }],
"lighthouse-core/audits/uses-responsive-images": ["error", { "maxLength": 0 }]
}
},
"upload": { "target": "filesystem", "outputDir": "./lhci-artifacts" }
}
}

Lighthouse CI w praktyce

Budżet bez egzekucji to deklaracja. Lighthouse CI (lhci) uruchamia audyt na każdym pull requeście i blokuje merge, gdy metryka przekroczy próg:

Terminal window
# instalacja i pierwszy lokalny audyt
npm install -D @lhci/cli
npx lhci autorun --config=lighthouserc.json
# w CI: deklaracja zadania (GitHub Actions)
# npx lhci autorun --config=./lighthouserc.json
# assert: "error" = build się nie uda, jeśli budżet przekroczony

Kombinacja “budżet w repo + audyt w CI + komentarz na PR” działa jak test wydajności: regresja jest widoczna w momencie, w którym powstała, a nie po miesiącu na produkcji. To jedyny sposób na utrzymanie wyników 90+ w długim terminie.

Kolejność działań: 90-minutowy plan

  1. Pomiar (10 min) – PageSpeed Insights + CrUX, zapisz baseline.
  2. Obrazy (20 min) – WebP/AVIF, srcset, lazy, fetchpriority.
  3. Fonty (15 min) – display swap, preload, subset, self-host.
  4. TTFB i cache (15 min) – CDN, nagłówki cache, brotli/gzip.
  5. JS (20 min) – defer, code splitting, ciężkie biblioteki lazy.
  6. CI z budżetem (10 min) – lighthouserc + zadanie w pipeline.

Po każdej zmianie powtórz pomiar – jedna metryka poprawiona kosztem drugiej to nie sukces.

Co dalej

Chcesz, żebym zoptymalizował twoją stronę do PageSpeed 90+ z budżetem wydajności pilnowanym w CI? Napisz do mnie – audyt wydajności z raportem i wdrożeniem zajmuje 3-5 dni, koszt od 1200 PLN.

Tagi:#pagespeed#core-web-vitals#lcp#performance#seo

Najczęściej zadawane pytania

Jaki wynik PageSpeed Insights jest dobry?
Powyżej 90 na mobile dla Performance to solidny wynik, ale liczy się nie suma, a Core Web Vitals: LCP poniżej 2,5 s, INP poniżej 200 ms i CLS poniżej 0,1. Wynik 100 z jedną metryką poza progiem to wciąż zła strona dla użytkowników i Google.
Dlaczego PageSpeed Insights pokazuje inne wyniki niż mój komputer?
Bo laboratorium symuluje słaby telefon (Moto G Power, 4G) i mierzy całą ścieżkę renderowania, a nie tylko czas wczytywania. Twój komputer z szybkim internetem nie pokazuje prawdziwego doświadczenia mobilnych użytkowników. Patrz też na dane terenowe (CrUX) z realnych przeglądarek.
Czy szybka strona naprawdę poprawia pozycje w Google?
PageSpeed jest potwierdzonym sygnałem rankingowym dla mobile (od 2018), a Core Web Vitals od 2021. Efekt jest najsilniejszy na słabych urządzeniach i przy dużej konkurencji. Realnie obserwuję wzrosty ruchu 5-20% po optymalizacji LCP z 4 s do 1,5 s u klientów.

Powiązane posty

MAHAWIR IWANOWSKI · WROCŁAW

Przyszłość organizacji — budowana tam, gdzie psychologia spotyka inżynierię, renderowana w kodzie, dostarczana z intencją.

Przyszłość Organizacji w Kodzie

AI · Fullstack · Psychology

© 2026 Mahawir Iwanowski · Wszystkie prawa zastrzeżone.