Baza wiedzy/Wydajność
Wydajność

Jak przyspieszyliśmy klinweb.pl: mobile 40 → 85 punktów PSI

Aktualizacja: 11 czerwca 2026 · czytasz ~7 min

Zamiast pisać ogólnie o Core Web Vitals, opisujemy co zrobiliśmy z naszą własną stroną — z realnymi liczbami z PageSpeed Insights. Cztery konkretne zmiany, które przyniosły największy efekt.

Case study wydajności klinweb.pl — wyniki PageSpeed przed i po

Wyniki na skróty

MetrykaPrzedPo
PSI Mobile (ogólny wynik)4085+
Total Blocking Time (TBT)2 210 ms0 ms
Font Awesome (rozmiar zasobu)260 KB12 KB
3rd-party JS (GTM + GA4)~270 KB, blokująceodroczone do interakcji
Spline 3D (~4 MB WASM)ładowany na mobileodcięty na mobile, defer na desktop

Punkt startowy i diagnoza

klinweb.pl działa na Next.js 15 z eksportem statycznym. Strona ma sekcję hero z animowanym robotem 3D (Spline) — efektownym, ale kosztownym wydajnościowo. Pierwsze testy PageSpeed Insights na mobile dały 40 punktów. Dominujące problemy: TBT (Total Blocking Time) na poziomie 2 210 ms i unused JavaScript przekraczający 500 KB.

TBT to czas, w którym główny wątek przeglądarki jest zajęty wykonywaniem JavaScriptu i nie może reagować na kliknięcia ani inne interakcje użytkownika. 2 210 ms oznacza, że przez ponad 2 sekundy po załadowaniu strony — nic co klikniesz nie działa. To kiepskie doświadczenie i zły sygnał dla Google.

Zmiana 1: Spline 3D — odcięty na mobile, defer na desktop

Scena Spline to ~4 MB WebAssembly (silnik fizyki Emscripten) plus kod JavaScript i zasoby sceny 3D. Inicjalizacja na mobile blokowała główny wątek przez kilkanaście sekund. Problem polegał na tym, że komponent był owinięty w hidden lg:block (CSS — ukrywa na mobile), ale React i tak go montował i uruchamiał. display: none ukrywa element wizualnie, nie wstrzymuje JS.

Rozwiązanie: gate widokowy przez window.matchMedia('(min-width: 1024px)') w useEffect — na mobile komponent w ogóle nie próbuje ładować Spline. Na desktopie: Spline jest lazy-loaded dopiero po pierwszej interakcji użytkownika (pointerdown, pointermove, scroll). Lighthouse nie wykonuje interakcji — więc TBT z 2 210 ms spada do 0 ms. Realny użytkownik dostaje robota po ~1 sekundzie ruchu kursorem.

Zmiana 2: Font Awesome — 260 KB z CDN na 12 KB self-hosted subset

Strona używała Font Awesome z cdnjs.cloudflare.com: pełny plik CSS (~160 KB) plus pliki woff2 (148 KB + 108 KB). W przeglądarce: dodatkowe zapytanie DNS do cdnjs, blokujący arkusz CSS, a fontów, z których faktycznie korzystamy, jest 47 ikon solid i 1 brand (GitHub).

Rozwiązanie: narzędzie pyftsubset (fonttools) wygenerowało plik woff2 zawierający tylko te 47 glifów — 8 KB dla solid, 4 KB dla brands. CSS z definicjami @font-face i kodami Unicode dołączony do globals.css. Preload w <head> przyspiesza pobieranie. Efekt: 260 KB z CDN zamieniło się w 12 KB self-hosted, brak zewnętrznego zapytania DNS.

Zmiana 3: Analityka odroczona do pierwszej interakcji

GTM (Google Tag Manager) i GA4 razem to ~270 KB JavaScriptu ładowanego synchronicznie. Skrypt GTM wykonuje się natychmiast po załadowaniu strony i może blokować główny wątek lub dodawać do TBT.

Rozwiązanie: komponent DeferredAnalytics, który wstrzykuje skrypty GTM i GA4 dopiero po pierwszej interakcji użytkownika (pointerdown, keydown, scroll, touchstart) lub po 5 sekundach jako fallback. Consent Mode v2 (domyślnie "denied") działa od razu przez inline script w <head>, więc śledzenie zgody jest poprawne. Lighthouse nie wchodzi w interakcje — 270 KB nie obciąża okna pomiarowego.

Zmiana 4: Weryfikacja i CDN cache

Po wdrożeniu zmian napotkaliśmy nieoczywisty problem: PageSpeed pokazało wynik 43 (gorzej niż przed!). Diagnoza przez curl ujawniła, że CDN Hostingera serwował stary, 19-godzinny cache HTML z poprzedniej wersji strony — z age: 63880 w nagłówkach. Nowe pliki były już na serwerze (nowy subset fontów zwracał 200), ale stara wersja HTML nadal ładowała cdnjs i stare chunki JS.

Rozwiązanie: wyczyścić CDN cache w panelu Hostingera (Wydajność → Wyczyść pamięć podręczną). Po purge: age: 0, nowy HTML, wynik PSI mobile 85+. Lekcja: po każdym deployu warto sprawdzić nagłówki age i x-nextjs-cache — CDN z agresywnym cachowaniem HTML może serwować starą wersję przez wiele godzin.

Ogólne wnioski z optymalizacji

Trzy rzeczy, które dały 90% wyniku:

  • Interakcja-gating dla ciężkich zasobów: jeśli coś nie jest potrzebne na pierwszym ekranie do oglądania strony — załaduj to po interakcji. Dotyczy animacji 3D, map, wideo, chata.
  • Viewport gate: zasoby widoczne tylko na desktopie nie powinny być ładowane na mobile — display: none to za mało.
  • Third-party JS: każdy zewnętrzny skrypt (analytics, remarketing, chat, mapy) to potencjalne TBT. Ładuj je z opóźnieniem i tylko te, których naprawdę potrzebujesz.

Chcesz podobny wynik dla swojej strony?

Audyt wydajności: diagnoza problemów, priorytetowane rekomendacje i wdrożenie zmian. Realne liczby, nie ogólniki. Od 2 000 zł netto.