Preskočite na sadržaj

Performanse / Beleška iz prakse

Smanjenje LCP-a na WordPress sajtu: šta je zaista važno

Uređen spisak onoga što zaista pomera Largest Contentful Paint na WordPress sajtu, i onoga što samo liči na rad na performansama.

Marko Stančić 8 minuta

Beleška s terena / Performanse

Na WordPress sajtu Largest Contentful Paint određuju četiri stvari, i to prilično strogim redom: koliko brzo server vrati HTML, da li browser može rano da otkrije glavnu sliku, da li išta blokira renderovanje pre nego što ta slika može da se iscrta, i koliko posla glavna nit obavlja dok to pokušava. Skoro sve ostalo što se prodaje kao optimizacija LCP-a na WordPress-u pomera broj tek neznatno.

Ovo nije studija slučaja i u njoj namerno nema brojeva pre i posle. Ono što sledi jeste redosled: šta prvo pogledati, šta zatim uraditi i šta prestati da radite jer samo liči na rad na performansama. Jedine brojke ovde su javni pragovi i ilustrativni primeri. Core Web Vitals smatra LCP dobrim na 2,5 sekunde ili manje, u zoni „treba popraviti” do 4 sekunde, a lošim iznad toga, i to mereno na 75. percentilu stvarnih učitavanja, a ne na jednom testu.

Utvrdite koji je element zapravo LCP element

Veliki deo rada na LCP-u koji nam donesu na pregled utrošen je na element koji nikada nije ni bio LCP element. Neko kompresuje logo, prebaci hero sliku u AVIF, pređe na jači server, a metrika se ne pomeri, jer je na tom šablonu LCP element bio naslov, prvi slajd karusela koji skripta ubaci nakon učitavanja ili pozadina sekcije definisana u CSS-u.

Browser vam to kaže direktno. Performance panel u Chrome DevTools obeležava LCP i pokazuje na čvor, Lighthouse ispisuje element u svojoj LCP proveri, a možete i sami da ga posmatrate iz konzole. Uključite „Preserve log”, nalepite ovo i osvežite stranicu:

// Važi poslednji unos: LCP se tokom učitavanja može promeniti više puta.
new PerformanceObserver((list) => {
  const entry = list.getEntries().at(-1);
  console.log(entry.element, Math.round(entry.startTime) + ' ms');
}).observe({ type: 'largest-contentful-paint', buffered: true });

Radite to po šablonu, a ne po sajtu. Početna stranica, arhiva kategorije, stranica proizvoda i tekst na blogu redovno imaju četiri različita LCP elementa, pa je popravka koja pomaže jednom od njih nebitna za ostala tri. Ako se ispostavi da je element tekst, dijagnoza se potpuno menja: kočnica je font i CSS ispred njega, a ne slika.

Radni princip

Odredite element pre nego što bilo šta dirnete. Vreme uloženo u čvor koji nije LCP element ne može da se pojavi u metrici, ma koliko dobro bilo uloženo.

Vreme do prvog bajta je donja granica, a ne jedan od faktora

Ništa ne može da se iscrta pre nego što HTML stigne, pa odgovor servera određuje budžet za sve što dolazi posle njega. Ako je vreme do prvog bajta 1,4 sekunde, celom ostatku stranice ostaje otprilike sekunda do dobrog praga, a nijedna slika još nije ni zatražena. Sam Google odgovor servera ispod 800 milisekundi smatra dobrim, a na WordPress-u je to pitanje hostinga i keširanja mnogo pre nego pitanje koda.

Keširanje cele stranice izbacuje PHP i bazu iz zahteva za neprijavljene posetioce, i zato keširana WordPress početna stranica na skromnom hostingu ume da bude brža od nekeširane na skupom serveru. Zanimljive su one stranice koje se iz tog keša ne mogu servirati: korpa i naplata, sve iza prijave i filtrirana pretraga u kojoj je query string deo odgovora. Na platformi Innovation Properties Group nekretnine se filtriraju po površini i nameni preko URL-a, pa se ti prikazi generišu po zahtevu, a njihovo vreme odgovora zavisi od baze i objektnog keša, a ne od statičkog fajla.

Tu trajni objektni keš zaslužuje svoje mesto. Bez njega WordPress na svakom nekeširanom zahtevu ponovo gradi iste upite za opcije, termine taksonomija i meta polja; sa Redis-om ili Memcached-om iza sebe, taj se posao plaća jednom. Još dve stvari tiho podižu donju granicu na starijim instalacijama: opcije sa uključenim autoload-om, koje su narasle na stotine kilobajta i čitaju se na svakom zahtevu, i plugini koji tokom renderovanja stranice šalju HTTP pozive napolje, radi provere licence ili preuzimanja fidova. Udaljeni poziv unutar zahteva znači da je vaš server brz onoliko koliko i tuđi.

Neka hero slika bude jeftina i lako uočljiva

Kada je LCP element slika, ishod skoro u potpunosti određuju četiri svojstva. Prvo, ispravne dimenzije: hero koji se prikazuje u širini od 1200 piksela ne treba da bude fajl od 2400 piksela, a WordPress će mirno poslužiti pogrešan ako tema uz inače uredan srcset ispiše neuredan atribut sizes. Drugo, format: WebP ili AVIF za fotografske hero slike, a nivo kvaliteta birajte gledajući u sliku, a ne verujući podrazumevanoj vrednosti plugina.

Treće, browser mora da zna da je slika važna. fetchpriority="high" je gura ispred svega ostalog što se bori za vezu, a LCP slika nikada ne sme da ide kroz lazy loading. Od verzije 6.3 WordPress oboje pokušava sam: preskače lazy loading na prvim slikama i dodeljuje visok prioritet onoj za koju veruje da je LCP kandidat. Ključna reč u toj rečenici je „veruje”. Heuristika gleda sadržaj u glavnom upitu, pa hero ispisan kroz template part iznad petlje, ubačen modulom page builder-a ili renderovan kao CSS pozadina redovno ostaje neprepoznat, a opšti prekidač „lazy load na sve” u optimizacionom pluginu onda tiho poništi i ostatak.

// Hero ispisuje template part, pa ga heuristika jezgra nikada ne vidi.
echo wp_get_attachment_image( $hero_id, 'hero-wide', false, [
    'fetchpriority' => 'high',
    'loading'       => 'eager',
    'sizes'         => '(min-width: 1200px) 1200px, 100vw',
] );

Četvrto, i najčešće previđeno, jeste uočljivost. Pozadinska slika definisana u CSS-u ne može da se zatraži dok se stil ne preuzme i dok se pravilo ne primeni, čime najvažniji piksel na stranici završava iza najsporijeg dela kritične putanje. Pravi img element u HTML-u preload skener vidi odmah. To je jedan od razloga zašto kod nas izrada WordPress sajtova po meri podrazumeva da hero markup stoji u šablonu koji kontrolišemo, a ne u shortcode-u page builder-a: ne možete dati prioritet elementu čiji markup ne vidite.

CSS i fontovi koji blokiraju renderovanje

CSS po svojoj prirodi blokira renderovanje, a tipičan WordPress frontend preuzima stil teme, block library, bundle page builder-a i po jedan fajl za svaki plugin pre nego što sme išta da iscrta. Polovina tih fajlova služi funkcionalnostima koje trenutna stranica ne koristi. Isključivanje stila na šablonima kojima ne treba nezahvalan je posao, ali direktno utiče na to kada LCP element uopšte sme da se pojavi, i vredi više od minifikacije fajlova koje nije trebalo ni tražiti.

Fontovi zaslužuju poseban prolaz, naročito kada je LCP element tekst. Uz podrazumevano font-display: block, tekst je nevidljiv dok se font učitava, a LCP se beleži tek kada se iscrta, pa spor fajl fonta postane metrika. swap odmah prikazuje rezervni font i prihvata pomeranje teksta; optional izbegava pomeranje i prihvata da deo posetilaca u toj poseti ostane na rezervnom fontu. Hostujte fontove kod sebe gde možete, koristite preconnect gde ne možete i radite preload samo za tačno one woff2 fajlove koji se koriste u prvom ekranu: svaki suvišan preload otima hero slici istu vezu, pa stranica na kraju bude sporija nakon „optimizacije”.

Odlaganje JavaScript-a nije isto što i uklanjanje

Dodavanje defer atributa na svaku skriptu najčešći je pojedinačni potez u ime Core Web Vitals-a na WordPress-u, pa vredi precizno reći šta on donosi. Odlaganje sklanja skriptu s puta parseru, i to je stvarna dobit. Ne sprečava da se fajl preuzme preko iste veze kojom ide i hero slika, niti da se izvrši na istoj glavnoj niti koja browseru treba za raspored, dekodiranje i iscrtavanje. Odloženi posao je premešten, a ne obrisan.

Uklanjanje je jači potez i počinje jednim pitanjem po skripti: da li je ovo potrebno prvom ekranu? Chat widgeti, bedževi recenzija, ugrađene mape, karuseli ispod preloma i većina analitike nisu. Njihovo učitavanje na interakciju ili u praznom hodu nije trik, nego tačan opis toga kada su potrebni. Cookie baner zaslužuje ručnu proveru: često se iscrtava iznad hero sekcije, ponekad je gura naniže, a povremeno i sam postane LCP element. jQuery je obično razlog zašto sajt ne može prosto sve da odloži: inline handleri koje ispisuju plugini računaju na to da je spreman, pa je uklanjanje te zavisnosti refaktorisanje, a ne kvačica u podešavanjima.

Redosled je veština. Spisak ume da primeni svako.

CDN spada u istu kategoriju delimične pomoći. On skraćuje razdaljinu, pa posetilac iz druge zemlje prestaje da plaća put preko okeana za svaki resurs. Na težinu ne utiče: predimenzionisana hero slika predimenzionisana je i sa edge servera, a CDN koji servira samo statičke fajlove ne menja koliko PHP-u treba da sastavi HTML. CDN sa keširanjem cele stranice na edge-u zaista popravlja vreme do prvog bajta, ali to nije usluga koju većina sajtova zapravo kupuje.

Verujte terenskim podacima, a ne jednom laboratorijskom merenju

Svaki broj iz pojedinačnog Lighthouse merenja laboratorijski je podatak, snimljen na simuliranom uređaju i usporenoj vezi, i razlikuje se od pokretanja do pokretanja nad istom, nepromenjenom stranicom. Takvo merenje je odlična dijagnostika, a loša presuda: pouzdano pokazuje koji je element LCP element i šta blokira renderovanje, ali nije dokaz da je izmena pomogla.

Brojevi na koje vredi reagovati dolaze od vaših posetilaca: Chrome UX Report, prikazan u izveštaju Core Web Vitals u Search Console-u ili u PageSpeed Insights-u iznad laboratorijskog dela, i sopstveno merenje na terenu ako dodate biblioteku web-vitals. Čitajte ih znajući šta su: pokretni prozor na 75. percentilu, grupisan po URL-u tamo gde saobraćaj to dozvoljava, a po celom domenu tamo gde ga nema dovoljno. Ti podaci kasne, pa se izmena objavljena ove nedelje neće videti sutra, a jedan brz šablon neće spasiti domen čiji stvarni saobraćaj završava na sporijim stranicama.

Ništa od ovoga ne proizvodi skor za uramljivanje. Proizvodi redosled poteza, što je korisnije, jer isti skor na dva WordPress sajta može tražiti suprotan posao: jednom treba sloj keširanja i razgovor o hostingu, drugom lakša hero slika i jedan stil isključen sa šablona. Znati pred kojim od ta dva slučaja stojite jeste ceo posao.

Praktičan zaključak

Odredite LCP element po šablonu, prvo popravite odgovor servera, pa hero sliku učinite jeftinom i uočljivom, pa raščistite putanju renderovanja. Proveravajte u terenskim podacima, a ne u jednom laboratorijskom merenju.

Pogledajte indeks dnevnika

Primena u praksi

Ispitajmo stvarno ograničenje

Ako performanse, arhitektura ili održivost usporavaju proizvod, donesite dokaze. Možemo definisati šta prvo treba da se promeni.

Razgovarajmo o projektu