Kiekvienas iš mūsų yra patyrę tą neapsakomą jausmą, kai puslapis kraunasi amžinybę. Spaudi nuorodą, laukiuosi, žiūri į baltą ekraną ar besisukantį ratą… ir galiausiai uždarai langą. Statistika rodo, kad net viena papildoma sekundė gali sumažinti konversijas iki 7%. O jei puslapis kraunasi ilgiau nei 3 sekundes? Na, tada jau pusė lankytojų tiesiog išeina. Taigi site speed optimizavimas – tai ne kažkoks priedas ar „gražu turėti” funkcionalumas, o kritinis verslo aspektas.
Šiandien pasigilinsime į techninius site speed optimizavimo aspektus. Ne teorines frazes apie tai, kaip „svarbu turėti greitą puslapį”, o konkrečius veiksmus, kuriuos galite įgyvendinti jau šiandien.
Serverio atsakymo laikas ir backend optimizacija
Pradėkime nuo to, kas vyksta už kulisų. Serverio atsakymo laikas (TTFB – Time To First Byte) yra pirmasis ir dažnai nepelnytai ignoruojamas aspektas. Galite turėti super optimizuotą frontend’ą, bet jei serveris atsako 2 sekundes, viskas veltui.
Pirmiausia – database queries. Esu matęs projektų, kur viename puslapyje vykdoma 50+ SQL užklausų. Ir ne bet kokių – N+1 problema ten klesti kaip piktžolės. Jei naudojate ORM (Eloquent, Doctrine ar panašiai), būtinai įjunkite query logging development aplinkoje. Pamatysite, kiek jūsų „nekaltas” kodas generuoja užklausų.
Praktinis patarimas: naudokite eager loading. Vietoj to, kad kiekvienam elementui darytumėte atskirą užklausą, įkelkite visus reikalingus ryšius iš karto. Laravel’e tai atrodo taip: Post::with('author', 'comments')->get(). Paprastas dalykas, bet efektas – kolosalus.
Antra – caching strategija. Redis ar Memcached turėtų būti jūsų geriausi draugai. Bet ne bet koks caching, o protingas. Nereikia cache’inti visko iš eilės. Identifikuokite „brangiausias” operacijas: sudėtingas agregacijas, išorinius API kvietimus, sunkias skaičiavimus. Būtent jas ir cache’inkite.
Dar vienas dažnai praleistas aspektas – opcache. Jei naudojate PHP, įsitikinkite, kad opcache yra įjungtas ir tinkamai sukonfigūruotas. Tai gali suteikti 2-3x greičio padidėjimą be jokių kodo pakeitimų. Tiesiog įjunkite ir užmirškite.
Asset’ų optimizacija ir bundle strategijos
Dabar pereikime prie frontend’o. CSS ir JavaScript failai – tai jūsų puslapio stuburas, bet dažnai ir didžiausia našta. Esu matęs projektų, kur viename puslapyje kraunama 15 skirtingų JavaScript bibliotekų, iš kurių realiai naudojama gal 20% funkcionalumo.
Pirmiausia – code splitting. Jei naudojate Webpack, Vite ar panašius bundler’ius, konfigūruokite juos taip, kad kodas būtų skaidomas į logiškus gabalus. Nereikia krauti viso admin panelo kodo į public landing’ą. Dynamic imports yra jūsų draugas: const module = await import('./heavy-module.js').
Tree shaking – dar vienas must-have. Modernūs bundler’iai gali automatiškai pašalinti nenaudojamą kodą, bet tam reikia teisingos konfigūracijos. Įsitikinkite, kad naudojate ES6 modules ir kad jūsų dependencies taip pat juos palaiko. Lodash yra klasikinis pavyzdys – vietoj import _ from 'lodash' naudokite import debounce from 'lodash/debounce'. Skirtumas gali būti 70KB vs 4KB.
Minification ir compression – tai elementaru, bet vis dar matau projektų, kur tai nedaroma. Gzip ar dar geriau Brotli compression turėtų būti įjungtas serveryje. Tai gali sumažinti failų dydį 70-80%. Nginx konfigūracijoje tai atrodo maždaug taip:
gzip on; gzip_types text/plain text/css application/json application/javascript; gzip_min_length 1000;
Paveikslėlių optimizacija ir modernūs formatai
Paveikslėliai paprastai sudaro 50-70% puslapio svorio. Ir čia yra didžiausios optimizavimo galimybės. Bet ne tiesiog „sumažinti kokybę” prasme, o protingai panaudoti modernius formatus ir technikas.
WebP ir AVIF – šie formatai turėtų būti jūsų default’as. WebP suteikia maždaug 25-35% mažesnius failus nei JPEG esant tai pačiai kokybei. AVIF dar geresnis – iki 50% mažesni failai. Bet čia svarbu suprasti – ne visi naršyklės palaiko šiuos formatus. Todėl reikia fallback strategijos.
Picture elementas HTML5 leidžia tai elegantiškai išspręsti:
<picture> <source srcset="image.avif" type="image/avif"> <source srcset="image.webp" type="image/webp"> <img src="image.jpg" alt="Description"> </picture>
Lazy loading – absoliutus must-have. Kodėl krauti paveikslėlius, kurie yra puslapio apačioje, jei vartotojas galbūt ten net nenuslinks? Native lazy loading dabar palaikomas visose moderniose naršyklėse: <img loading="lazy" src="image.jpg">. Taip paprastai.
Responsive images – naudokite srcset atributą, kad skirtingiems ekranams būtų kraunami skirtingo dydžio paveikslėliai. Nėra prasmės mobile įrenginyje krauti 4K rezoliucijos nuotrauką. Tai atrodo taip:
<img srcset="small.jpg 480w, medium.jpg 800w, large.jpg 1200w"
sizes="(max-width: 600px) 480px, (max-width: 1000px) 800px, 1200px"
src="medium.jpg" alt="Description">
Critical rendering path ir above-the-fold optimizacija
Čia tampame šiek tiek filosofiški. Vartotojui iš tikrųjų nerūpi, ar visas puslapis užsikrovė per 1 sekundę. Jam rūpi, ar tai, ką jis mato ekrane (above-the-fold), užsikrovė greitai. Tai vadinama perceived performance.
Critical CSS – tai CSS, reikalingas pirminiam puslapio atvaizdavimui. Šį CSS reikia inline’inti tiesiai į HTML head’ą, o likusį CSS krauti asinchroniškai. Taip vartotojas iš karto mato suformatuotą puslapį, net jei visi asset’ai dar neužsikrovė.
Yra įrankių, kurie tai daro automatiškai – critical, critters. Jie analizuoja jūsų HTML ir CSS, identifikuoja critical CSS ir inline’ina jį. Webpack ar Vite plugin’ai gali tai daryti build procese.
Font loading strategija – dar viena dažnai ignoruojama sritis. FOIT (Flash of Invisible Text) ir FOUT (Flash of Unstyled Text) yra tos problemos, kurias visi esame matę. Tekstas arba nematomai mirga, arba keičiasi šriftas po kelių sekundžių.
Sprendimas – font-display: swap CSS property. Tai liepia naršyklei iš karto rodyti tekstą sisteminiu šriftu, o kai custom šriftas užsikrauna, jį pakeisti. Taip pat galite preload’inti kritinius šriftus:
<link rel="preload" href="font.woff2" as="font" type="font/woff2" crossorigin>
HTTP/2, HTTP/3 ir resource hints
Protokolų evoliucija taip pat turi didelę įtaką greičiui. HTTP/2 įvedė multiplexing – galimybę siųsti kelis request’us vienu connection’u. Tai panaikino senąją „domain sharding” praktiką, kur asset’ai buvo dedami į kelis subdomain’us.
HTTP/3 (QUIC) eina dar toliau – naudoja UDP vietoj TCP, kas sumažina latency. Jei jūsų CDN palaiko HTTP/3 (Cloudflare, Fastly palaiko), įjunkite jį. Nereikia jokių kodo pakeitimų, tiesiog serverio konfigūracija.
Resource hints – tai būdas pasakyti naršyklei, ką ji turės krauti ateityje. Yra keletas tipų:
- dns-prefetch – resolv’ina DNS iš anksto:
<link rel="dns-prefetch" href="//example.com"> - preconnect – užmezga connection’ą (DNS + TCP + TLS):
<link rel="preconnect" href="https://example.com"> - prefetch – krauna resource’ą, kuris bus reikalingas kitame puslapyje:
<link rel="prefetch" href="next-page.html"> - preload – krauna resource’ą, kuris bus reikalingas šiame puslapyje:
<link rel="preload" href="critical.css" as="style">
Bet atsargiai su preload – jei preload’insite per daug, galite faktiškai sulėtinti puslapį, nes naršyklė prioritizuos tuos resource’us prieš kitus, galbūt svarbesnius.
JavaScript execution optimizacija
JavaScript yra ne tik download’o problema, bet ir execution problema. Didelis JS bundle’as ne tik ilgai kraunasi, bet ir ilgai parse’inasi bei execute’inasi. Ypač mobile įrenginiuose, kur CPU galia ribota.
Async ir defer atributai – pagrindai, bet vis dar matau projektų, kur visi script’ai yra head’e be jokių atributų. Skirtumas paprastas: defer krauna script’ą paraleliai, bet execute’ina tik po DOM parse’o. Async krauna ir execute’ina iš karto, kai tik užsikrauna. Daugeliu atvejų defer yra saugesnis pasirinkimas.
Long tasks – tai JavaScript operacijos, kurios užblokuoja main thread ilgiau nei 50ms. Jos daro puslapį „užšalantį”. Chrome DevTools Performance tab rodo šias tasks raudonais kampeliais. Jei matote daug long tasks, reikia refactorinti kodą.
Vienas būdas – naudoti Web Workers sunkioms operacijoms. Jei turite sudėtingus skaičiavimus, duomenų processingą ar panašiai, perkelkite tai į worker’į. Taip main thread lieka laisvas UI interakcijoms.
Kitas būdas – requestIdleCallback API. Tai leidžia jums execute’inti ne kritinį kodą tik tada, kai naršyklė yra idle. Pavyzdžiui, analytics, tracking ar kiti „nice to have” dalykai gali laukti:
requestIdleCallback(() => {
// Non-critical code here
sendAnalytics();
});
Monitoring ir continuous optimization
Optimizacija nėra vienkartinis veiksmas. Tai nuolatinis procesas. Kodas keičiasi, pridedamos naujos features, bibliotekos atsinaujina. Tai, kas buvo greita prieš mėnesį, gali būti lėta dabar.
Real User Monitoring (RUM) – tai būdas matuoti tikrų vartotojų patirtį. Google Analytics, New Relic, Datadog – visi turi RUM funkcionalumą. Svarbu matuoti ne tik puslapio load time, bet ir Web Vitals metricas: LCP (Largest Contentful Paint), FID (First Input Delay), CLS (Cumulative Layout Shift).
Šios metrikos tiesiogiai įtakoja Google search ranking’ą, tad jos yra ne tik user experience, bet ir SEO klausimas. LCP turėtų būti < 2.5s, FID < 100ms, CLS < 0.1. Jei jūsų skaičiai blogesni, turite problemų.
Performance budgets – nustatykite limitus. Pavyzdžiui, „JavaScript bundle negali būti didesnis nei 200KB”, „puslapio load time negali viršyti 3s”. Integruokite šiuos check’us į CI/CD pipeline. Webpack turi performance hints, kurie gali warn’inti ar net fail’inti build’ą, jei viršijami limitai.
Lighthouse CI – puikus įrankis automatizuotam performance testing’ui. Galite jį integruoti į GitHub Actions ar kitą CI sistemą, ir kiekvienas PR bus testuojamas performance požiūriu. Jei naujas kodas sulėtina puslapį, pamatysite tai iš karto.
Kai greitis tampa kultūra, o ne feature’u
Baigiant norisi pasakyti, kad site speed optimizavimas nėra vieno žmogaus ar vienos komandos darbas. Tai turėtų būti įmonės kultūros dalis. Kiekvienas developer’is, designer’is, product manager’is turėtų galvoti apie performance.
Pradėkite nuo paprastų dalykų – įjunkite compression’ą, optimizuokite paveikslėlius, išvalykite nenaudojamą kodą. Tai gali suteikti 30-40% greičio padidėjimą per kelias valandas darbo. Paskui eikite giliau – database optimizacija, caching strategijos, code splitting.
Naudokite įrankius – Lighthouse, WebPageTest, Chrome DevTools. Jie duoda konkrečias rekomendacijas, ne abstrakčias frazes. Ir svarbiausia – matuokite. Negalite optimizuoti to, ko nematote. Nustatykite metricas, stebėkite jas, reaguokite į pokyčius.
Performance optimizavimas niekada nesibaigia. Visada yra ką gerinti, visada yra naujų technikų, naujų formatų, naujų galimybių. Bet tai ir įdomu – kiekvienas optimizavimas yra mažas victory, kuris tiesiogiai pagerina tūkstančių ar milijonų vartotojų patirtį. Ir tai, manau, yra gana cool.

