Proč je inicializace stránky tak pomalá?

Máte úžasný design stránky přesně napasovaný pro konkrétní zařízení, rozlišení a prohlížeč, ale než se načte, trvá to několik desítek sekund, což spolehlivě odradí jakéhokoliv návštěvníka?

Třídy v rootu

Často je problém to, že v inicializaci stránky nastavujete pomocí jQuery (nebo libovolného jiného frameworku) třídy do různých prvků podle nejrůznějších podmínek:

if ($.browser.webkit) {
    $('body').addClass('isWebkit');
}
if ($.browser.msie) {
    $('body').addClass('isIE');
}
//...
if (window.innerWidth<window.innerHeight) {
    $('html').addClass('portraitMode');
}
//...

Tento přístup se často používá pro automatickou aplikaci stylů v závislosti na konkrétním zařízení (různá rozlišení, rozdělení pro desktop, iPhone a Android, apod.) nebo prohlížeči (IE často nezná nejnovější definice, webkit obsahuje chyby, apod.):

/* IE11, Chrome 22, Firefox 24, Opera 15 */
.layout { display: flexbox; }
/* workaround pro ostatní */
.oldBrowser .layout { display: table; }

#footbar { position: fixed; bottom: 0; }
/* http://css.chobits.ch/renderovaci-chyby-ve-webkitu/ */
.isWebkit #footbar {
  -webkit-transform:translateZ(0);
}

Kromě toho, že podobné definice samy o sobě zpomalují vykreslování (viz Optimalizace selektorů), tak každé zavolání metody $().addClass() (stejně jako $().removeClass(), $().toggleClass(), apod.) vynutí překreslení daného prvku a všech prvků v něm se nacházející (protože prohlížeč neví, jestli kvůli nové třídě nemusí aplikovat další CSS definice). A v případě, že změníte třídu prvků BODY nebo HTML, musí prohlížeč překreslit celou stránku.

Řešení je několik:

1. Změna třídy jen jednou

Nejlepší řešení (vlastně ne nejlepší, ale nejjednodušší, pokud potřebujete zrychlit existující stránku) je nevolat metodu $().addClass() pro každou třídu zvlášť, ale jen jednou až po té, co zjistíte, jaké všechny třídy musíte nastavit (nebo naopak umazat). Pak dojde k překreslení stránky jen jednou:

//Původní kód
if ($.browser.webkit) {
    $('body').addClass('isWebkit');
    // stránka se překresluje...
}
if ($.browser.msie) {
    $('body').addClass('isIE');
    //stránka se překresluje...
}
//...
if (window.innerWidth<window.innerHeight) {
    $('html').addClass('portraitMode');
    ///stránka se překresluje..
}
//...
//Vylepšený kód
var classes = [];
if ($.browser.webkit) {
    classes.push('isWebkit');
}
if ($.browser.msie) {
    classes.push('isIE');
}
//...
if (window.innerWidth<window.innerHeight) {
    classes.push('portraitMode');
}
//...
$('body').addClass(classes.join(' '));
//stránka se překresluje jen jednou...

Díky tomu, že třídy jen ukládáte do proměnné a $().addClass() zavoláte až na konci, nedochází k opakovanému překreslování stránky a vše se tak vykreslí rychleji.

Také si všimněte, že původní kód měnil třídy jak BODY tak HTML zatímco nový kód vše nastavuje jen do BODY, čímž se opět ušetří jedno překreslení (a důvod k rozdělení žádný není).

Samozřejmě tento způsob lze použít jen v případě, že veškerá nastavování tříd se provádí na jednom místě (tedy v jedné funkci). Obejít by to šlo např. tím, že třídy budete ukládat do nějaké globální proměnné (což nedoporučuji, lepší by byl nějaký singleton, service, apod.) a pak je ve správný okamžik zpracovat (např. na konci BODY.onload()).

2. lokální třídy

Druhý způsob spočívá v tom, že pokud pro konkrétní prvek potřebujete nějakou CSS výjimku, nastavíte danému prvku speciální třídu a následně pomocí JavaScriptu změníte třídy jen těmto prvkům. Díky tomu bude prohlížeč nucen překreslit jen menší část stránky a bude to rychlejší.

   ...
   <div id="footbar"
       class="needWebkit needIE">
      ...
   </div>
   ...
if ($.browser.webkit) {
    $('.needWebkit').addClass('isWebkit');
}
if ($.browser.msie) {
    $('.needIE').addClass('isIE');
}
#footbar {
    position: fixed; bottom: 0;
    display: flexbox;
}
/* http://css.chobits.ch/renderovaci-chyby-ve-webkitu/ */
#footbar.isWebkit {
    -webkit-transform:translateZ(0);
}
/* old layout - příklad */
#footbar.isIE {
    display: table;
}

Tento způsob je lepší i v tom, že selektor #footbar.isWebkit se pracovává rychleji než .isWebkit #footbar, protože pracuje jen s jedním elementem a nemusí prohledávat jeho rodiče.

Napsat komentář

Vaše emailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *

Tato stránka používá Akismet k omezení spamu. Podívejte se, jak vaše data z komentářů zpracováváme..