Hvem glor – din bror Den ikke-så-personlige blog af Bjørn Klinggaard

13apr/102

Sådan laver du hurtigere websider

Efter påpegelse af Niels Gamborg og i forlængelse af mit forrige indlæg Sådan laver du perfekt CSS kommer her en tilføjelse, som omhandler performance aspektet. Selvfølgelig skal man ikke være ligeglad med performance, hvorfor man skal huske at optimere sine websider. Hvis det ikke er for din egen skyld og/eller pengepung, så for at brugerne får en bedre (og hurtigere) oplevelse. Ligeledes tyder det desuden på, at Google vil (og til dels allerede gør) vægte hurtigere hjemmesider højere.
Jeg har opstillet nogle simple punkter, som gerne skulle hjælpe med at opnå hurtigere indlæsningstider på dine websider.

0: Minimer HTTP-requests

Jo færre requests jo bedre. Den største og nok nemmest måde at reducere dine indlæsningstider på dine websider ligger i antallet af HTTP-requests, hvorfor du skal eliminere unødvendige requests.

Hvorfor
Browsere bruger i dag cirka 80% af deres tid på at hente eksterne filer såsom stylesheets, scripts, billeder etc. Hver fil er lig med et request, dog henter browsere disse requests parallelt (på nær script-filerne), og alt afhængig af browser, kan de have x antal forbindelser kørende på samme host på samme tid.  Herunder er opstillet nogle eksempler på, hvor mange forbindelser per host samt max forbindelser de mest benyttede browsere kan håndtere:

    Browser           |   Connection per hostname   |   Max connections
Internet Explorer 8                   6                        57
Chrome 4                              6                        55
Chrome 5                              6                        40
Firefox 3.5+3.6                       6                        30
Safari 4                              5                        60
Opera 10                              4                        20
Internet Explorer 7                   2                        60
Internet Explorer 6                   2                        56

Andre browsere og flere detaljer omkring de enkelte browsere kan findes på browserscope, som er et open source projekt startet af Steve Souders og Lindsey Simon.

Hvordan
Ja nu ved vi, hvorfor det er en god ide at minimere HTTP-requests, men hvordan gør vi det egentlig i praksis?
Der findes flere måder at gøre det på. Jeg vil her præsentere 2 måder, som jeg selv finder nyttige, brugbare og bruger til dagligt.

a) Kombinerede filer: Så snart det er muligt, skal man kombinere sine scripts og stylesheets således, at alle ens stylesheets bliver samlet i en fil og ligeledes med sine scripts. På denne måde kan man spare requests.
Det kan dog være svært, hvis scripts og stylesheets varierer meget fra side til side. Her må man gå ind og vurdere den enkelte situation, og kigge på hvad der mest gavner indlæsninghastigheden. Man skal være opmærksom på, at fx billeder i stylesheets også generer requests, så hvis tendensen på din side ikke er, at brugeren besøger mange sider, og du har meget forskelligt styling fra side til side, kan man spare requests ved at benytte sig af en side-modulær CSS opbygning. Men som tommelfingerregel skal man samle sine stylesheets samt scripts i en fil.

b) CSS Sprites: CSS Sprites reducerer antallet af billede requests. Kort fortalt går det ud på, at man samler flere af sine billeder i et billede, og vha. background-position styre hvilken sekvens af billedet, man vil vise. Hvis du ikke kender til sprites, kan du læse mere omkring emnet her:

CSS Sprites: Image Slicing’s Kiss of Death af David Shea

The Mystery Of CSS Sprites af Sven Lennartz

CSS Sprite: What they are ... af Chris Coyier

Eller kigge nærmere på hvordan jeg har lavet min top menu.

1: Placerer stylesheets i toppen

Der er to grunde til at placerer stylesheets i toppen.

  1. W3 dikterer, at stylesheets skal være i toppen (head), medmindre det er inline-styling.
  2. Ved at placere stylesheets i toppen opnår man, at ens side loader progressivt, hvilket er vigtigt, hvis din side har meget indhold, eller brugeren sidder bag en langsom forbindelse. Siden viser indholdet så snart, det er klart, og brugeren har en indikation af, at siden er ved at loade. Denne indikation er meget vigtig for brugervenligheden. Hvis man derimod indsatte stylesheets nær bunden, ville man i mange browsere (eksempelvis Internet Explorer) miste den progressiv hentning og stå tilbage med en hvid blank side, da browsere blokerer renderingen for at forhindre at skulle gentegne elementer, der måtte ændre sig.

2: Placerer scripts i bunden

Grunden til at scripts skal være i bunden er, at scripts blokerer for den parallelle hentning, hvorfor resten af dit indhold må vente til scriptet er færdighentet. Derfor placerer altid dine scripts i bunden, når det er muligt. Der findes selvfølgelig situationer, hvor du ikke kan, fx hvis du indsætter markup via document.write, hvilket jeg dog ikke er den store fan af eller initialisere ting i dit script i den øvre del af dit HTML dokument.

3: Stylesheets og scripts skal være eksterne

Nu kommer jeg til at modsige mig selv, men der er en mening med galskaben. I første punkt fik du at vide, at du skulle spare på HTTP-requests, og undgå dem så snart det var muligt, men nu fortæller jeg dig, at du skal gemme dine stylesheets samt scripts eksternt frem for at gemme dem inline, og dermed generer et ekstra request per fil. Igen kommer det an på situationen, men oftest er der mest at hente ved at gemme dem eksternt. Ved at gemme dem eksternt bruger du som sagt et ekstra request per fil, men da browsere cacher filerne, kan det være en fordel, hvis du eksempelvis bruger de samme filer på flere sider. Ved at gemme dem inline spare du det ekstra request, men HTML dokumentet bliver tungere, og filerne bliver indlæst ved hver page load. Når dine filer derimod er cachet generer de ikke et ekstra request og HTML dokumentet er ligeledes lettere.

4: Minify

Ved at minify sine stylesheets og scripts fjerner man unødvendige tegn og luft, og gør dem derved lettere at hente. Der findes forskellige værktøjer til at minify med:

  1. YUI Compressor: YUI er et af de mest kendte og mest effektive minify værktøjer. Det er skrevet i Java, og man skal afvikle det på sin computer. Det gode ved YUI er selvfølgelig den effektive algoritme som minifyer, men også at den kan minify scripts såvel som stylesheets.
  2. CSS Compressor: Online værktøj, som kan minify dit CSS ud fra forskellige indstillinger.
  3. Closure compiler: Googles svar på et script minify værktøj, som eftersigende skulle være bedre end YUI. Compileren kan både downloades eller benyttes online samt indstilles efter behov og temperament.

5: Fjern duplikater

Punktet burde egentligt ikke have været med på listen, da det giver sig selv. Men jeg har set steder, hvor de stadig forekommer, duplikater af scripts. Ved at have duplikater forøges indlæsningstiden. Internet Explorer laver et ekstra unødvendigt request, hvorimod Firefox godt kan se, at det er det samme script. Dog spilder begge browsere tid på at evaluere scriptet to gange, så undgå at have duplikerende scripts.

6: Reducer DOM-elementer

En tommelfingerregel er, at jo flere elementer du har på en side, jo tungere er den at renderer. Sørg derfor altid for at have så ren og meningsfuld markup som muligt. Mange elementer på en side gør det ligeledes sværere for JavaScript at tilgå dem. En måde du kan undersøge, hvor mange elementer en side har, er ved hjælp af Firebug. Skriv blot følgende i konsol vinduet:

document.getElementsByTagName('*').length

7: Brug dine subdomæner

HTTP 1.1 specifikationen anbefaler, at browsere ikke downloader mere end 2 komponenter parallelt per host. Ved at gemme dine billeder på flere forskellige hosts, kan du opnå mere end 2 parallelle downloads ad gangen, og dermed gøre din side hurtigere. Steve Souders har lavet et lille eksempel, hvor han illustrerer forskellen på at gemme sine billeder på et host kontra to.

8: Undgå @import

Brug <link /> frem for @import. Internet Explorer opfatter filer indsat ved hjælp af @import som link-tags, der er indsat i bunden af siden.

9: Undgå filters

Hvis du vil have transparente png billeder i Internet Explorer 6, kan du bruge Microsofts eget filter, AlphaImageLoader. Dette er dog ikke anbefalingsmækværdi! Problemet ligger i at filteret blokerer rendering af siden og fryser browservinduet, mens billedet bliver hentet. Filteret forøger ligeledes brugen af computerens hukommelse. Undgå derfor at bruge dem, og brug i stedet gif eller png8 billeder eller nogle af de andre alternativer der findes, hvis du vil understøtte semi-transparente billeder i IE6.

10: Undgå tomme billede referencer

Tomme billede referencer resulterer i ekstra og nytteløse serverkald:

<img src="" alt="Tomt billede reference" />

Nicholas C. Zakas har skrevet en udmærket artikel, der beskriver problemet rigtig godt.

11: Komprimerer dine billeder

Hvis du som jeg ikke altid selv klipper dit grafik og dermed gemmer det, kan der opnås store besparelser ved selv at genkomprimerer billederne. Uden at slå alle designer over en kam, så tænker de ikke på størrelsen.

12: Komprimerer dine komponenter

GNU zip eller også kaldet gzip er en komprimeringsmetode, som kan spare dig adskillige kilo bytes og dermed minimere svar tiderne. Vel og mærket hvis server samt klient understøtter det. Fra og med HTTP/1.1 er web-klienter begyndt at understøtte komprimering med Accept-Encoding i headeren af HTTP-request'et, fx:

Accept-Encoding: gzip, deflate