PageSpeed optimalizácia: mobil skóre z 44 na 97 v troch krokoch
Tri zmeny posunuli LCP na kariera.kami-profit.sk z 9,1 sekundy na 2,6 sekundy a mobil skóre z 44 na 93. Kľúčové zistenie: všetky tri boli nevyhnutné - každá samostatne nestačila.
Kariérny web kariera.kami-profit.sk mal mobil skóre PageSpeed 44. LCP (Largest Contentful Paint) - čas, za ktorý sa načíta hlavný vizuál stránky - bol 9,1 sekundy. Hranica pre "dobré" LCP podľa Google je 2,5 sekundy. Tri zmeny to opravili na 2,6 sekundy a skóre vyskočilo na 93. Tu je presne čo sme urobili a prečo to fungovalo.
Zmena 1: hero obrázok preč z externého servera
Hlavný obrázok bol uložený na WordPress serveri klienta ako JPG s veľkosťou 647 KB. Sťahoval sa v plnom rozlíšení na mobile aj desktope. Navyše z externého servera - prehliadač musel najprv vyriešiť DNS, nadviazať TLS spojenie a až potom začal sťahovať.
Presunuli sme ho lokálne, skonvertovali na WebP formát a vytvorili dve veľkosti: desktop verzia 159 KB a mobilná verzia (768 px šírka) 65 KB. Na servovanie správnej veľkosti podľa zariadenia slúži HTML element picture so source media atribútom - prehliadač na mobile stiahne 65 KB namiesto 647 KB. Na konverziu na WebP slúži nástroj cwebp - klasický sips na macOS WebP nepodporuje.
Zmena 2: preload obrázka priamo v head
Aj keby bol obrázok lokálny a malý, prehliadač ho musel najprv objaviť. Bez preloadu vyzerá sekvencia takto: stiahni HTML, nájdi stylesheet, zablokuj renderovanie, stiahni a sparsuj CSS, vyrenderuj DOM, nájdi img tag v hero sekcii, začni sťahovať obrázok. Na mobile to trvalo viac ako 9 sekúnd.
Riešenie: link rel="preload" as="image" s atribútom fetchpriority="high" priamo v head stránky - zvlášť pre mobile a zvlášť pre desktop veľkosť. Prehliadač začne sťahovať obrázok súbežne s parsovaním HTML, nie až po CSS a DOM. Atribút media je pri preloade povinný - bez neho prehliadač stiahne obe veľkosti naraz a efekt sa stratí.
Zmena 3: kritické CSS inline, zvyšok asynchrónne
Každý stylesheet v head blokuje celé vykresľovanie stránky, kým sa nestiahne a nesparsuje. Náš CSS súbor mal 44 KB - na pomalej mobile sieti to pridalo sekundy pred prvým vykreslením.
Riešenie: CSS rozdelíme na dve časti. Kritické štýly (tokeny, reset, navigácia, hero sekcia, tlačidlá - asi 2 KB) vložíme priamo inline do style tagu v head. Zvyšok načítame asynchrónne cez preload pattern s onload handlerom. Stránka sa vykreslí okamžite bez čakania na stiahnutie celého CSS súboru.
Prečo museli fungovať všetky tri zmeny spolu
Každá zmena samostatne dáva iba čiastočný výsledok:
- Preload bez lokálneho obrázka: prehliadač ho objaví skoro, ale stále sťahuje 647 KB z externého servera
- Lokálny WebP bez preloadu: obrázok je malý, ale prehliadač ho objaví neskoro - po CSS a DOM
- Async CSS bez preloadu obrázka: odblokuje prvý render, ale LCP obrázok stále čaká na objavenie
Všetky tri sa navzájom zosilnili. Výsledok: LCP z 9,1 sekundy na 2,6 sekundy. Mobil skóre zo 44 na 93. Dostupnosť (accessibility) 100/100.
Bonus: tichá CSS chyba, ktorá trvala mesiace
Pri optimalizácii sme objavili aj chybu, ktorá trvala dlho bez povšimnutia. CSS malo pravidlo pre scrollovaný stav navigácie pod názvom #nav.s, ale JavaScript pridal triedu scrolled. Tieto dve sa nikdy nezhodli - tmavé pozadie navigácie pri scrollovaní sa teda nikdy neaplikovalo.
Vizuálne to vyzeralo správne, pretože za navigáciou bol tmavý hero obrázok, ktorý poskytoval kontrast. Lighthouse ale nevidí obrázky za priehľadnými elementmi - vypočíta kontrast podľa CSS pozadia. Polopriesvitná navigácia nad bielou stránkou = svetlosivé efektívne pozadie. Biely text na svetlosivom pozadí = kontrast 1,1:1. Výsledok: accessibility skóre kleslo zo 100 na 96.
Oprava bola jednoduchá - zosúladiť názov CSS triedy s tým, čo JavaScript skutočne pridáva. Tento typ chyby je zákerný: web vyzerá perfektne, automatizované testy ho odhalia až keď scrollujú stránku počas auditu.
Zhrnutie
Performance optimalizácia webu nie je o jednej "magic" zmene. Je to o odstránení viacerých prekážok naraz, ktoré sa navzájom blokujú. Na kariera.kami-profit.sk to boli tri: externý veľký obrázok, neskorá detekcia obrázka a blokovanie renderu CSS. Opravené spolu: skóre 93, LCP 2,6 sekundy, dostupnosť 100.