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.
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:
- PageSpeed Insights dla URL (5 pomiarów – wyniki w labie bywają rozrzucone),
- CrUX Dashboard (dane terenowe z ostatnich 28 dni) – to one decydują o tym, czy Google uzna stronę za “fast”,
- 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ń:
- Format – WebP (a przy wsparciu AVIF) zamiast JPEG/PNG. Te same wymiary, ~30-50% mniejszy plik.
- Wymiary – wygeneruj warianty dla każdego breakpointa (srcset + sizes), nie skaluj 2000px obrazu do 400px w CSS.
- Lazy loading – obrazy poniżej linii cięcia dostają
loading="lazy"; hero i LCP-element nigdy. fetchpriority="high"– na obraz hero, żeby przeglądarka zaczęła go pobierać natychmiast.- 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-face–size-adjustredukuje 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/asyncblokują renderowanie.modulepreloadzamiastpreloaddla 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:
# instalacja i pierwszy lokalny audytnpm install -D @lhci/clinpx 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 przekroczonyKombinacja “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
- Pomiar (10 min) – PageSpeed Insights + CrUX, zapisz baseline.
- Obrazy (20 min) – WebP/AVIF, srcset, lazy, fetchpriority.
- Fonty (15 min) – display swap, preload, subset, self-host.
- TTFB i cache (15 min) – CDN, nagłówki cache, brotli/gzip.
- JS (20 min) – defer, code splitting, ciężkie biblioteki lazy.
- 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.
Najczęściej zadawane pytania
Jaki wynik PageSpeed Insights jest dobry?
Dlaczego PageSpeed Insights pokazuje inne wyniki niż mój komputer?
Czy szybka strona naprawdę poprawia pozycje w Google?
Powiązane posty
- devops
Cloudflare dla WordPressa: pełna optymalizacja wydajności i bezpieczeństwa
Jak skonfigurować Cloudflare (Free/Pro) dla WordPressa krok po kroku: cache, APO, WAF, Bot Fight Mode, page rules, CDN. Realne wyniki pomiarów i konfiguracja dla Polski.
7 min - aiAI
GEO vs SEO: jak optymalizować treści pod wyszukiwarki AI w 2025
Generative Engine Optimization to nowa dyscyplina SEO. Jak pisać treści, które cytuje ChatGPT, Perplexity i Gemini. Praktyczne techniki z przykładami kodu i danymi.
5 min