Zoeken op Blue 2 Blond

Hoe we JavaScript laten groeien en browsers het verwerken

Iedereen snapt: stel JavaScript uit en laad alleen JavaScript in dat je gebruikt. Dit resulteert in betere performance en betere conversie. Maar hoe doe je dat in de basis?

In een lang epistel heeft Addy Osmani het al eens blootgelegd (gebruik je plugin/library toepassingen, dan zeker de moeite van het lezen waard): JavaScript is de meest kostbare bron dat we computers als ook smartphones voorschotelen, doordat het interactiviteit op vele manieren kan beïnvloeden.

Het belangrijkste: laadt alleen JavaScript code dat je gebruikt, 200kb aan JavaScript is immers niet hetzelfde als 200kb aan afbeeldingen, doordat JavaScript nog uitgevoerd moet worden door de browser. Dit heeft impact op user metrics als First Input Delay (FID) en Time to Interactive (TTI), wat ten koste kan gaan van de conversie op een website.

JavaScript asynchroon, defer en onderaan de body

JavaScript is voor de browser pijnlijk, doordat de browser JavaScript eerst zal gaan uitvoeren, voordat het begint met inkleuren van de webpagina. Oftewel, een potentiële klant zal pas een logo, afbeelding of koptekst te zien krijgen, indien JavaScript geheel is uitgevoerd. De browser wacht bewust, omdat de kans groot is dat JavaScript impact gaat hebben op de content van de webpagina (DOM structuur, om exact te zijn).

Wat veel developers en marketeers inmiddels weten: stel JavaScript uit, zodat de browser direct begint met inkleuren van je webpagina en de bezoeker het idee blijft houden dat er iets gebeurt in het scherm. Gevolg: de bezoeker klikt minder snel weg.

Echter, er zijn legio manieren om JavaScript te vertragen, namelijk:

  • asynchroon laden (niet voor andere bronnen);
  • deferred laden (oftewel, het laden uitstellen);
  • een script-tag onderin de body plaatsen, in plaats van in de head.

Asynchrone JavaScript

Wanneer het async attribuut wordt gebruikt, wordt het JavaScript bestand alvast gedownload, maar zal de browser niet wachten tot de download klaar is. Echter, zodra de browser het signaal krijgt dat het JavaScript bestand is gedownload, stopt het met verdere parsen van de HTML code, en wordt de JavaScript code direct uitgevoerd.

JavaScript defer

Het JavaScript gedrag lijkt bij gebruik van het defer attribuut op het gedrag van async, met als verschil dat de browser de HTML code ongestoord verder zal parsen. Pas als het parsen voltooid is, zal de browser de JavaScript file gaan uitvoeren, ongeacht of de download van het bestand al in een eerder stadium klaar was.

Afbeeldingen zijn afkomstig van bitsofco.de.

Een combinatie is ook mogelijk, zoals een script-tag in de body plaatsen in combinatie met asynchroon (async) of uitgesteld (defer) laden. Wat het verschil is en hoe de browser er mee omgaat, heeft Addy Osmani opgenomen op zijn website.
Combinatie van defer en async als attribuut is gezien de huidige brede browser ondersteuning voor beide individuele attributen overbodig.

JavaScript defer versus onderin de body?

De juiste toepassing zal volledig afhankelijk zijn van de techniek van je website of webapplicatie. In de meeste gevallen zul je echter defer willen gebruiken, in plaats van de JavaScript verwijzing onderin de body te plaatsen. In beide gevallen kun je alvast de basis van een webpagina in laten kleuren door de webbrowser, om vervolgens achteraf verdere content-mutaties te doen.

Let wel: beperk content-mutaties tot een minimum, want elke contentmutatie kan er voor zorgen dat de browser opnieuw elementen moet tekenen, wat een impact heeft op de TTI-metric en daarmee performance.

Resource hints

Het gevolg van het uitstellen van JavaScript, is dat de browser de code niet direct zal downloaden. Op het moment dat de browser klaar is met inkleuren van het scherm, staan de volgende taken voor je webbrowser nog op de lijst:

  1. downloaden van de JavaScript file(s);
  2. uitpakken (decompress);
  3. parsen van de JavaScript code;
  4. uitvoeren van de JavaScript code.

In de poging om metrics als First Contentful Paint (FCP) en First Meaningful Paint (FMP) te verbeteren, wordt een gebruiker gedwongen te wachten tot verdere uitvoer van code. Middels resource hints kun je de browser alvast commanderen om stap 1 en 2 (het downloaden en uitpakken van JavaScript files) in een vroeg stadium uit te voeren.

Omdat het uitvoeren pas in een later stadium plaats vindt, ben je tijdens andere werkzaamheden van de browser, de main-thread (en daarmee andere browser-taken) niet aan het blokkeren. Op het moment dat met stap 3 afgetrapt wordt, is het document al gedownload.

Groei van JavaScript

Maatregelen als bovenstaand hebben we aan onszelf te danken. We hebben ons laten leiden door Third Party toepassingen. Middels externe scripts konden we ineens voorzien in buttons om content te delen, om social media content in te voegen of interactie en animaties mogelijk te maken. Maar dit kwam met een zware kostenpost.

Async en defer ondersteuning en toepassing

Al eens eerder benoemde ik in een artikel, hoe de omvang van Third Party JavaScript van 2011 naar 2018 met 806% steeg. Gaat performance je aan het hart? Ga dan vooral na wat je werkelijk nodig hebt en hoe je overige keer op meer ideale wijze kunt inladen. En ga na of asynchroon of defer beter bij je situatie past, of wellicht juist geen van beide.

Async and defer wordt al sinds 2010 door Firefox en Chrome ondersteund, in 2012 gevolgd door Safari en Internet Explorer. Sinds dit statistiek gemeten wordt door HTTP Archive (2015), komt toepassing van asynchroon steeds meer op, ten koste van blokkerende JavaScript(s).

Bonuslijst: third party scripts verantwoordelijk voor excessieve JS uitvoertijd uit categorieën als Video, Analytics, Social sharing en marketing.

Meer technieken: code splitting en tree shaking

Met middelen als defer en async kun je voorzien in betere DOMContentLoaded (DCL), als ook FCP en FMP metrics. Desondanks zal de impact op de verdere performance niet verminderd worden, wanneer er niet meer concessies worden gedaan. Een bezoeker of potentiële klant zal nog steeds moeten wachten tot verdere JavaScript is uitgevoerd, voordat de browser gereed is om in te spelen op interactie vanuit de gebruiker.

Dit kan met tree shaking en code splitting. Hoe wij hierin voorzien binnen websites voor onze opdrachtgevers, verdient een eigen artikel.