Chci probrat appkuMáte SW problém?
Zpět na blog
Webový vývojPerformanceWebOptimalizaceCore Web Vitals

Performance optimalizace webových aplikací

Lukáš Huso5. května 20269 min čtení
Performance optimalizace webových aplikací
Photo: Marc-Olivier Jodoin / Unsplash

Rychlost webové aplikace není jen technická metrika. Je to přímo měřitelný faktor, který ovlivňuje konverze, SEO pozice a spokojenost uživatelů. Google to ví, a proto v roce 2021 začal Core Web Vitals používat jako rankingový signál. Amazon zjistil, že každých 100 ms prodlevy stojí 1 % prodejů. A vaši uživatelé mají jednoduché pravidlo: pokud stránka nenačte obsah do 3 sekund, odejdou jinam.

53 %
uživatelů odejde, pokud se stránka nenačte do 3 sekund
1 %
ztráta prodejů na každých 100 ms zpoždění (Amazon)
30–50 %
zlepšení LCP samotnou optimalizací obrázků

Core Web Vitals -- co měří a proč

Google definoval tři metriky, které hodnotí uživatelský zážitek z načítání a interakce se stránkou.

LCP (Largest Contentful Paint) měří, za jak dlouho se vykreslí největší viditelný element na stránce -- typicky hero obrázek, hlavní nadpis nebo velký blok textu. Cílová hodnota je pod 2,5 sekundy. LCP nad 4 sekundy Google hodnotí jako špatný.

LCP je často nejtěžší metrika na optimalizaci, protože závisí na celém řetězci: DNS lookup, TCP/TLS handshake, server response time, stahování HTML, parsování CSS, stahování a dekódování obrázku. Slabý článek v kterémkoli bodě zpomalí celkový výsledek.

INP (Interaction to Next Paint) nahradil v březnu 2024 starší metriku FID (First Input Delay). Zatímco FID měřil jen první interakci, INP měří odezvu na všechny interakce během celé návštěvy a reportuje nejhorší hodnotu. Cíl je pod 200 ms. Prakticky to znamená, že po kliknutí na tlačítko, otevření menu nebo zadání textu musí stránka vizuálně reagovat do 200 ms.

INP je problematická zejména u JavaScript-heavy aplikací. Dlouhé synchronní operace na hlavním vláknu blokují vykreslování a způsobují "zamrznutí" interface. Řešení spočívá v rozdělení práce na menší úlohy, použití web workerů pro náročné výpočty a minimalizaci hlavního vlákna.

CLS (Cumulative Layout Shift) měří vizuální stabilitu -- jak moc se elementy na stránce posouvají během načítání. Cíl je pod 0,1. Každý zažil situaci, kdy chtěl kliknout na odkaz a v posledním momentu se stránka posunula, protože se nad ním načetl obrázek nebo reklama. Přesně to CLS penalizuje.

Optimalizace obrázků -- největší quick win

Obrázky tvoří typicky 40-60 % celkové váhy stránky. Jejich optimalizace je proto nejrychlejší cesta ke zlepšení výkonu.

Formáty nové generace. WebP nabízí o 25-35 % menší velikost než JPEG při srovnatelné kvalitě. AVIF jde ještě dál -- 50 % úspora oproti JPEG. Oba formáty dnes podporují všechny moderní prohlížeče. Pokud stále servírujete JPEG a PNG, přepněte na WebP jako výchozí formát s JPEG fallbackem.

<picture>
  <source srcset="hero.avif" type="image/avif" />
  <source srcset="hero.webp" type="image/webp" />
  <img src="hero.jpg" alt="Hero image" />
</picture>

Responzivní obrázky. Neservírujte 2000px široký obrázek na mobilním zařízení s 400px viewportem. Atribut srcset a element <picture> umožňují servírovat správnou velikost pro každé zařízení. V Next.js komponenta Image toto řeší automaticky.

Lazy loading. Obrázky pod foldem (mimo viditelnou část obrazovky) by se měly načítat až když se k nim uživatel přiblíží. Nativní atribut loading="lazy" funguje ve všech moderních prohlížečích a nevyžaduje JavaScript. Pozor ale na LCP element -- ten by naopak měl mít loading="eager" nebo žádný atribut, aby se načetl co nejdříve.

Správné rozměry. Vždy specifikujte width a height atributy na <img> elementech. Prohlížeč díky nim může vyhradit prostor pro obrázek ještě před jeho stažením, čímž se eliminuje layout shift (CLS). V CSS použijte aspect-ratio pro responzivní obrázky.

Code splitting a tree shaking

Moderní JavaScript aplikace mají tendenci nabývat na velikosti. Framework, knihovny, utility, polyfilly -- není neobvyklé vidět bundle o velikosti 500 KB a více. Uživatel ale na úvodní stránce potřebuje zlomek tohoto kódu.

Code splitting rozdělí aplikaci na menší chunky, které se načítají na vyžádání. V React a Next.js používáte dynamic() import pro komponenty, které nejsou potřeba při prvním renderování. Modální okna, grafy, administrační panely -- všechno, co se zobrazí až po interakci uživatele.

const Chart = dynamic(() => import("../components/Chart"), {
  loading: () => <ChartSkeleton />,
});

Tree shaking automaticky odstraní nepoužitý kód při build procesu. Funguje ale pouze s ES moduly (import/export). Pokud importujete celou knihovnu (import _ from "lodash"), bundler nemůže odstranit nepoužité funkce. Importujte specificky (import debounce from "lodash/debounce").

Bundle analýza. Než začnete optimalizovat, potřebujete vědět, co zabírá místo. Nástroj webpack-bundle-analyzer (nebo @next/bundle-analyzer pro Next.js) vizualizuje obsah vašeho bundlu. Často najdete překvapení -- knihovna pro formátování dat, která zabírá 70 KB, ale používáte z ní jednu funkci. Nebo dva různé HTTP klienti, protože každá knihovna si přitáhla vlastní.

Optimalizace fontů

Webové fonty jsou tichým zabijákem výkonu. Běžný Google Font má 20-100 KB, a pokud je na kritické cestě vykreslování, blokuje zobrazení textu.

font-display: swap. Tato CSS vlastnost říká prohlížeči, aby text zobrazil okamžitě systémovým fontem a po načtení webového fontu ho vyměnil. Uživatel vidí obsah okamžitě místo prázdného místa. Nevýhodou je krátký "záblesk" při výměně fontu (FOUT -- Flash of Unstyled Text), ale to je výrazně lepší než neviditelný text (FOIT -- Flash of Invisible Text).

Self-hosting místo Google Fonts CDN. Překvapivě, self-hosting fontů je dnes rychlejší než Google Fonts CDN. Důvod: prohlížeč musí navázat nové spojení k fonts.googleapis.com a potom k fonts.gstatic.com, což přidává latenci. Při self-hostingu je font na stejné doméně jako vaše stránka.

Subsetting. Pokud vaše stránka používá jen latinku, nepotřebujete znaky pro cyrilici, řečtinu nebo arabštinu. Font subsetting může snížit velikost fontu o 50-80 %. Nástroj glyphhanger analyzuje vaše HTML a vytvoří font obsahující pouze použité znaky.

Caching strategie

Správný caching je rozdíl mezi stránkou, která se načítá 3 sekundy, a stránkou, která se načítá 300 ms.

Browser cache s immutable assets. Statické assety (JS, CSS, obrázky) by měly mít hash v názvu souboru (app.a1b2c3.js) a Cache-Control: max-age=31536000, immutable. Prohlížeč je stáhne jednou a rok je neověřuje. Při změně kódu se změní hash a prohlížeč stáhne novou verzi.

Stale-while-revalidate. Pro HTML stránky a API odpovědi je vhodná strategie stale-while-revalidate. Prohlížeč okamžitě zobrazí cachovanou verzi a na pozadí ověří, jestli existuje novější. Uživatel vidí obsah okamžitě a při příštím načtení dostane aktualizovanou verzi.

Service Worker pro offline. Pro progresivní webové aplikace (PWA) Service Worker umožňuje cachovat celou aplikaci a servírovat ji offline. Workbox od Googlu zjednodušuje implementaci a nabízí předpřipravené strategie pro různé typy obsahu.

CDN -- obsah blíž k uživateli

Content Delivery Network distribuuje statické assety na servery po celém světě. Když uživatel v Praze požaduje obrázek, dostane ho ze serveru ve Frankfurtu (20 ms) místo z originu v USA (150 ms).

Pro české projekty je CDN relevantní zejména pokud máte mezinárodní publikum. Cloudflare nabízí generous free tier a kromě CDN přidává i DDoS ochranu, automatickou kompresní (Brotli), a edge caching. Vercel a Netlify mají CDN integrovaný.

Důležité: CDN pomáhá se statickými assety, ale neřeší pomalý backend. Pokud vaše API odpovídá za 2 sekundy, CDN s tím nic neudělá. Zaměřte se nejdřív na server response time (TTFB by měl být pod 600 ms) a teprve pak řešte distribuci.

SSR versus SSG -- vliv na výkon

Způsob, jakým generujete HTML, má přímý dopad na výkon.

Static Site Generation (SSG) pregeneruje HTML při buildu. Stránky se servírují jako statické soubory z CDN -- žádný server-side výpočet, minimální TTFB. Ideální pro obsah, který se nemění často: marketing pages, blog, dokumentace.

Server-Side Rendering (SSR) generuje HTML na serveru při každém requestu. TTFB je vyšší (server musí provést výpočet), ale obsah je vždy aktuální. Vhodné pro personalizovaný obsah, dashboardy, e-commerce s dynamickými cenami.

Incremental Static Regeneration (ISR) kombinuje výhody obou přístupů. Stránka se pregeneruje při buildu, ale po vypršení TTL se na pozadí regeneruje s aktuálními daty. Uživatel dostane vždy rychlou cachovanou verzi, která je maximálně X sekund stará.

Pro většinu marketingových webů a blogů je SSG optimální volba. Pro aplikace s uživatelským obsahem zvažte SSR nebo ISR.

Měření -- lab data versus field data

Jedním z nejčastějších omylů je optimalizovat pouze na základě Lighthouse skóre.

Lab data (Lighthouse, WebPageTest) měří výkon v kontrolovaných podmínkách -- na konkrétním zařízení, s konkrétním připojením, bez rozšíření prohlížeče. Jsou skvělé pro diagnostiku a srovnání před a po optimalizaci. Ale neříkají vám, jaký zážitek mají vaši skuteční uživatelé.

Field data (Chrome UX Report, Web Vitals knihovna) měří výkon u reálných uživatelů na reálných zařízeních s reálným připojením. Google pro rankingový signál používá field data, ne lab data. Stránka s Lighthouse skóre 95 může mít špatné Core Web Vitals ve field data, pokud ji většina uživatelů navštěvuje na pomalých mobilech.

Jak měřit správně. Používejte Lighthouse pro diagnostiku a identifikaci problémů. Sledujte field data přes Google Search Console (sekce Core Web Vitals) nebo přes knihovnu web-vitals integrovanou do vaší analytiky. Nastavte si RUM (Real User Monitoring) pro kontinuální sledování výkonu.

WebPageTest.org je nezastupitelný nástroj pro hloubkovou analýzu. Filmový pás (filmstrip) ukazuje přesně, co uživatel vidí v každé desetině sekundy. Waterfall diagram odhalí, které zdroje blokují rendering. A možnost testovat z různých lokací a na různých zařízeních dává realistický obrázek.

Praktický postup optimalizace

1. Audit

Změřte aktuální stav -- Lighthouse, Core Web Vitals v Search Console, bundle analýza. Bez dat nemůžete optimalizovat.

2. Quick wins -- obrázky

Přepněte na WebP/AVIF, přidejte lazy loading, nastavte správné rozměry. Často zlepší LCP o 30-50 %.

3. Code splitting

Odložte načítání komponent, které nejsou potřeba při prvním vykreslení. Analyzujte bundle a odstraňte zbytečné závislosti.

4. Caching a CDN

Immutable cache pro statické assety, stale-while-revalidate pro dynamický obsah, CDN pro globální distribuci.

5. Kontinuální monitoring

Nastavte RUM (Real User Monitoring), sledujte field data a pravidelně porovnávejte s benchmarky.

Pokud nevíte, kde začít, postupujte podle tohoto pořadí -- od nejvyššího dopadu k nejnižšímu.

Za prvé, změřte aktuální stav. Spusťte Lighthouse audit, podívejte se na Core Web Vitals v Search Console, analyzujte bundle size.

Za druhé, optimalizujte obrázky. Přepněte na WebP/AVIF, přidejte lazy loading, nastavte správné rozměry. Toto samotné často zlepší LCP o 30-50 %.

Za třetí, implementujte code splitting. Odložte načítání komponent, které nejsou potřeba při prvním vykreslení. Analyzujte bundle a odstraňte nepotřebné závislosti.

Za čtvrté, nastavte caching. Immutable cache pro statické assety, stale-while-revalidate pro dynamický obsah, CDN pro globální distribuci.

Za páté, optimalizujte fonty. Self-hosting, font-display: swap, subsetting.

Každý krok změřte a porovnejte s předchozím stavem. Optimalizace výkonu je iterativní proces, ne jednorázová akce.

Závěr

Performance optimalizace není technický detail, který se řeší na konci projektu. Je to fundamentální aspekt uživatelského zážitku, který ovlivňuje úspěch celé aplikace. Dobrou zprávou je, že většina optimalizací nevyžaduje přepis aplikace -- stačí systematický přístup, správné nástroje pro měření a disciplína implementovat best practices od začátku vývoje. Investice do výkonu se vrací v lepších konverzích, vyšších pozicích ve vyhledávačích a spokojenějších uživatelích.

Spočítejte si cenu na míru

Konfigurátor vám za 2 minuty ukáže orientační cenu přesně pro váš projekt.

Související články

SEO katastrofy: Weby, které Google nenajde

SEO katastrofy: Weby, které Google nenajde

Skutečné příběhy SEO katastrof — od neviditelných SPA po nákup tisíců zpětných odkazů. Jak nezničit svůj web v očích Googlu.

9. dubna 20266 min čtení
Bezpečnost webových aplikací: OWASP Top 10 v praxi
Webový vývojBezpečnostOWASP

Bezpečnost webových aplikací: OWASP Top 10 v praxi

Praktický průvodce OWASP Top 10 zranitelnostmi. Reálné příklady, prevence v moderních frameworcích a jak zabezpečit webovou aplikaci.

31. března 20269 min čtení
Hostingové horory: Proč záleží, kde běží vaše appka
Webový vývojHostingServer

Hostingové horory: Proč záleží, kde běží vaše appka

Aplikace na notebooku pod stolem, hosting za 50 Kč co nezvládne 100 uživatelů, poskytovatel co zkrachoval přes noc. Příběhy z praxe.

7. května 20266 min čtení