Na het optimaliseren van de serverinstellingen is het deze keer de beurt aan de optimalisatietechnieken die je kan toepassen op de frontend, in je HTML, CSS en Javascript.
In het inleidende artikel haalde ik enkele cijfers aan: 80 à 90% van de snelheid van een website wordt bepaald bij het ophalen van de verschillende componenten. Dit ophalen van assets gebeurt aan de hand van HTTP requests.
Achtergrondinformatie
In de RFC 2616 staat het volgende te lezen:
Clients that use persistent connections SHOULD limit the number of simultaneous connections that they maintain to a given server. A single-user client SHOULD NOT maintain more than 2 connections with any server or proxy.
De eerste draft van deze RFC dateert van januari 1997 en toen was die connectielimiet nog te verantwoorden, omdat breedbandconnecties toen heel zeldzaam waren.
To find a decent balance, IE and Firefox by default restrict users to 6 connections total and 2 connections per host for HTTP 1.1 connections.
Omwille van historische redenen wordt standaard in browsers het aantal simultane connecties naar dezelfde host beperkt tot 2. De geavanceerde browsergebruiker kan die waarden wel aanpassen, maar de modale bezoeker van je website zit dus met die limiet van 2 connecties per host.
Opmerking: Internet Explorer 8 zal de limiet optrekken van 2 naar 6 connecties per host.
Downloaden van componenten
De performantie van je website hangt, zoals je nu al zal doorhebben, grotendeels af van het aantal componenten op de pagina.
Bij een standaard browserinstallatie, downloaden die componenten parallel in groepjes van 2 per hostnaam.
Gelukkig kan je deze beperking omzeilen en dit door de componenten te spreiden over 2 hostnamen. Zo kan je de response time dus halveren.
Je zou hier nog verder in kunnen gaan en bijvoorbeeld 4 of meer hostnames gebruiken, maar omwille van de vertraging die optreedt bij DNS lookups, kan dit dan weer een negatieve impact hebben op de performantie. Het kan in sommige gevallen de server CPU, bandbreedte of aantal simultane connecties belasten.
Volgens onderzoek van Yahoo! is het spreiden van componenten over 2 tot 4 hostnamen ideaal voor performantie.
Verschillende grote sites plaatsen hun statische componenten onder een andere hostname: Yahoo! op yimg.com, Youtube op ytimg.com en Amazon op images-amazon.com. Je hoeft zelfs geen afzonderlijke domeinnaam aan te kopen, het kan evengoed met een subdomein.
Ik haalde de techniek ook al aan in het vorige artikel uit de reeks met optimalisatietips, meerbepaald in de sectie over cookies:
Bij de meeste websites staan de cookies gewoon op de root (/), wat die cookie dan voor elk object zet. Daarom is het aan te raden om je statische content op een aparte domein, of subdomein te plaatsen, waarop dan geen cookies worden geplaatst.
Wij hebben er een gewoonte van gemaakt om de statische content (CSS, Javascript files, afbeeldingen, …) onder een subdomein te plaatsen. Meestal iets als static.example.be.
Minder HTTP Requests
Je kan de performantie van je website dus drastisch verhogen door het aantal HTTP requests tot een minimum te beperken.
In het vorige artikel legde ik uit hoe je via enkele serveraanpassingen componenten kan cachen voor hergebruik… Maar ook op de frontend kan je nog enkele performantie verhogende technieken toepassen.
CSS Sprites
Bij CSS Sprites worden verschillende afbeeldingen gecombineerd in 1 grotere afbeelding. Voorbeelden vind je op verschillende sites, waaronder die van BBC (voorbeeld), Yahoo (voorbeeld), Google (voorbeeld), … Met CSS sprites kan je dus al een groot aantal requests reduceren tot 1 of slechts enkele requests.
Een bijkomend voordeel van CSS sprites is dat de gecombineerde afbeelding, in de meeste gevallen ook kleiner in bestandsgrootte is dan de optelsom van de verschillende afzonderlijke groottes en dit doordat er minder kleurentabellen en formaatinformatie moet opgeslagen worden.
Op complexe websites met een groot kleurenpallet kan je dan opteren om eventueel meerdere sprites te gebruiken.
Zo heeft het ontwikkelingsteam van de BBC website 60 externe afbeeldingen kunnen samenvoegen tot 3 sprites: 1 voor achtergronden, 1 voor kleurverlopen en 1 voor de afgeronde hoekjes.
Combineren van scripts en stylesheets
De meeste websites gebruiken meerdere scripts of stylesheet documenten. Vaak kunnen deze zonder probleem gecombineerd worden: dus alle Javascript files combineren tot 1 script file, en alle CSS files tot 1 stylesheet document. Uitzonderingen zijn natuurlijk de print stylesheet en de stylesheets specifiek voor Internet Explorer (via conditional comments).
Je kan, zoals ons, een onderscheid maken tussen development en productie omgevingen en blijven werken met afzonderlijke files tijdens het ontwikkelen van de website en deze dan op de productieserver samenvoegen, eventueel via een geautomatiseerd server-side script.
Comprimeren van CSS en Javascript files
Je kan HTTP compressie toepassen op serverniveau, om bestandsgroottes in realtime te verkleinen, maar je kan je ook baseren op minifying. Hierbij worden onnodige karakters uit de files verwijderd. Het gaat dan om commentaarregels, spaties, tabinsprongen, newlines, … Het resultaat is een compactere (maar minder leesbare) file. Ideaal dus voor productieomgevingen.
Obfuscation gaat als techniek nog verder, waarbij het moeilijker wordt om de source files correct te interpreteren. Het vervangt functienamen en variabelen door kortere karakters (a, b, c, …). Deze compressiemethode kan echter ook bugs in je code introduceren. Wees dus voorzichtig bij gebruik.
Enkele populaire tools om je code te minimaliseren zijn: JSMin en onze persoonlijke favoriet, YUICompressor.
Onze methodiek bij Javascript files is: de namen van variabelen en functies zo compact mogelijk te houden en dan de verschillende files via een PHP script samen te voegen, om daarna te comprimeren (via de minify techniek) en dan via HTTP compressie in de browser te bezorgen.
Gemiddeld kan je met de minify techniek op de bestandsgrootte zo’n 20% besparen. Als je het combineert met HTTP compressie kan je er vaak nog eens een extra 5% van krijgen.
CSS optimalisatie
We kennen ondertussen allemaal het belang van CSS. Maar toch kan je ook met CSS nog de mist in gaan. Vooral bij grotere sites is het soms moeilijk om het aantal CSS regels beperkt te houden. Vandaar deze quote van Nate Koechley:
We spend a lot of time on familiarizing ourselves with all the properties and values of CSS, but the power of professional CSS lies in choosing the right selectors.
Het komt er dus op neer om je CSS compact te houden, ondermeer door het kiezen van de juiste selectors.
Je kan je CSS ook optimaliseren door:
- Geen te lange namen te kiezen bij je ids en classes
- Shorthand CSS properties toepassen
- Modulaire aanpak volgen en groeperen van gemeenschappelijke kenmerken
Gebruik geen @import
Ondanks het gemak van het importeren van CSS via @import, is het ten stelligste af te raden. Zelfs al staat de @import regel helemaal bovenaan de HTML pagina, dan nog zullen die files pas als allerlaatste ingeladen worden. Het verhindert dus de vlotte rendering van de website.
Het laden van de externe CSS files gebeurt best via de <link> tag in de head van het document.
Javascript: plaats je externe scripttags niet in de head
In tegenstelling tot externe CSS files, plaats je scripts best onderaan de pagina. Vele developers doen dit net in de head van het HTML document, maar dat heeft een negatieve inpact op de performantie.
Tijdens het laden van zo’n script wordt namelijk het downloaden in parallel tijdelijk geblokkeerd. De reden hiervoor is dat het script document.write kan bevatten, waardoor de structuur van de HTML nog voor het renderen kan wijzigen.
Een andere reden voor dit gedrag is omdat browsers willen vermijden dat het ene script onbedoeld voor het andere wordt geladen. Hierdoor zouden Javascript errors kunnen optreden, wanneer de ene file afhankelijk is van de andere.
Tijdens het downloaden van Javascript files, worden er dus geen andere componenten gedownload… Als je wil dat de website snel wordt weergegeven, dan plaats je dus best Javascript files onderaan de pagina.
Deferred scripts
Je zou eventueel het attribuut defer kunnen toevoegen aan je script in de head, waarmee je aangeeft dat die file geen document.write zal bevatten, maar helaas werkt dat niet in Firefox en dus eigenlijk is dat geen optie.
Preloading
Door te preloaden kan je optimaal gebruik maken van de tijd nadat de browser alle huidige componenten heeft ingeladen, om nieuwe te downloaden, die je misschien nodig hebt op volgende pagina’s.
We onderscheiden 3 scenario’s waarin je assets kan preloaden:
-
Unconditional preload:
In dit geval worden de assets altijd ingeladen wanneer je bepaalde een pagina bezoekt. Een goed voorbeeld hiervan is de homepage van Google. Hierop downloaden ze de sprite met de afbeeldingen voor de resultaten pagina van zodra de homepage klaar is met laden (onLoad event). Wanneer de gebruikers dus iets zoekt en op de resultatenpagina terecht komt, dan zit de sprite al in de browsercache.
-
Conditional preload:
Hier start je het downloaden van sommige componenten of scripts van zodra de gebruiker bepaalde controls of widgets begint te gebruiken. Voorbeelden hiervan vind je op de Yahoo! homepage.
-
Anticipated preload:
Bij het redesignen van een website kan je een tijdje op voorhand de stylesheets, scripts of afbeeldingen van het nieuwe design laten downloaden. Wanneer de nieuwe site dan gelanceerd wordt, blijft hij toch snel presteren, omdat de componenten in de browsercache van de trouwe bezoekers zullen zitten.
En verder
Tot zover dus de theorie. In het volgende artikel ga ik met concrete voorbeelden en cijfers aantonen hoeveel voordeel je kan halen uit caching, het beperken van het aantal HTTP requests, de CSS en Javascript technieken, … En vooral met welke tools je de performantie kan meten, om zelf ook aan de slag te gaan. Stay tuned!
Links naar dit artikel
Momenteel zijn er nog geen links naar dit artikel.

Reacties
Goed artikel. Eén opmerking over het combineren van stylesheets. Print styles kunnen gewoon mee in hetzelfde stylesheet worden opgenomen, dat gaat dan zo:
@media screen { ... }@media print { ... }
Ook IE stylesheets kan je in principe opnemen in hetzelfde stylesheet via deze techniek. Alle andere browsers moeten dan wel een paar nutteloze kB extra downloaden natuurlijk.
Goed artikel en ook weer actueel, nu Google de laadtijd van een pagina gaat meewegen als rankingfactor.