Jak jsme snížili loadování z osmi sekund pod dvě
aneb co udělat pro bleskový load html appky
Libor Mořkovský, CTO Behavio
Jedna z věcí, které v Behaviu vyvíjíme, je Minute: lehká mobile-first dotazníková aplikace.
Minutové dotazníky pro zaměstnanecké, zákaznické i marketingové výzkumy, plné obrázků a měřící hlavně rychlé reakce a asociace. Rychlost načítání otázek i samotného dotazníku je v takové aplikaci klíčová. A právě loading dotazníku trval v naší prvně nahozené verzi 8 sekund. Po troše úprav klesl pod dvě sekundy. Minute přes dva roky funguje s minimem úprav a je furt rychlá. V Lighthouse má stále skóre 99/100. V tomhle blogu vám ukážeme, jak jsme toho dosáhli.
Tip 1: Ne každý módní design-pattern je dobrý pro každý use-case
V Behaviu dost sledujeme různé frameworky, baví nás občas vyhlédnout za hranice mainstreamu.. Na front-endu nás tehdy bavil inovativní přístup v Google Polymer. Jeho součástí je design pattern PRPL, který preferuje nebundlovaný build. To znamená uložit aplikaci třeba do 30 fragmentů s tím, že se jednotlivé fragmenty budou lépe cachovat u klientů a zbytečné round-trips vyřeší HTTP/2 push. Je to fajn nápad, pokud na vaši stránku chodí lidé denně a vy děláte drobné změny v některých částech. Jenže náš use-case je trochu opačný: potřebujeme doručit jeden dotazník za čas, s kompletní funkcionalitou, co nejrychleji. A příště zase jiný. Kouskováním tedy nic neušetříme, jen nám navíc vzniknou latence dané nadbytečnou komunikací o jednotlivých balíčcích (nebo přibude komplexita zajišťující, aby se všechny balíčky odeslaly přes HTTP/2 push).
Krok jedna je tedy: dvakrát se zamyslet nad tím, jestli můj výchozí framework neoptimalizuje na něco jiného, než co zrovna teď potřebuji.
Tip 2: Co všechno můžu vyhodit
Tip 3: Mini Firebase
Používáme cloudovou databázi Firebase Realtime Database od Googlu a opět: má to spoustu výhod. Jenomže v tomto případě byl kompletní Firebase balík větší než celá naše appka. A to bylo trochu moc. Co s tím? Při pročítání dokumentace Firebase, jsme si všimli, že kromě kompletního SDK podporuje Realtime Database také REST API. To vypadalo ideálně pro naše použití, kde potřebujeme z databáze co nejdříve (jednou) číst a potom párkrát zapsat.
Malý wrapper, který zajistí opakování requestů při nestabilním připojení jsme měli za den napsaný a otestovaný. Dvě sta řádků, 5 kB a jako bonus využití ?x-http-method-override, kterým si ušetříme CORS preflight request, což opět vylepší chování aplikace na nespolehlivém připojení.
Nedávno jsme zjistili, že vývojáři z Firebase připravili odlehčenou knihovnu pro Firestore, což je novější verze jejich databáze, úplně stejným způsobem. Takže máte práci ušetřenou.
Tip 4: Obrázková CDN
Co tvoří největší část dat, která posíláme? Obrázky. Sice nám nezdržují load samotné aplikace, ale mohou být už v první otázce. Což pro uživatele je vlastně to samé. Jde objem dat z obrázků nějak minimalizovat? Přinejmenším tak, že nebudeme do žádného zařízení stahovat ani o pixel větší obrázky, než v jakém je pak zobrazí. Naštěstí pro něco takového existují služby: například imgix. Nahrajete do ní obrázky ve vysokém rozlišení, a ta už je pak distribuuje do jednotlivých zařízení přesně v té velikosti, která je pro daný mobil potřeba. A navíc pozná podle hlaviček v requestu, jaká verze prohlížeče si o obrázek žádá – a podle toho imgix vybere nejlepší metodu komprese, kterou je daný prohlížeč schopen zobrazit.
Tip 5: Není rychlosti bez měření
Mezi dobrými radami co udělat, aby byly „stránky rychlé“, a opravdu rychlými stránkami je ještě propast: realita. Naše stránky budou „rychlé“ jenom tehdy, když u většiny uživatelů splní nějakou představu o tom, jak vypadají rychlé stránky. Poněkud vágní pojmy z předchozí věty nabírají konkrétní hodnoty díky Core Web Vitals. Vykreslení největší části stránky (LCP, Largest Contentful Paint) by u nejméně třech čtvrtin uživatelů mělo proběhnout do 2,5 sekundy.
Na měření je aktuálně nejtěžší použít správné API pro získání čísel. Moderni API jako PerformanceNavigationTiming nejsou dostupná ve všech prohlížečích, starší API vracejí jiná čísla. Naše řešení je reportovat ze starších prohlížečů čísla odděleně, abychom nemíchali jablka a hrušky. Odeslání a následný reporting v Google Analytics už je hračka.