Navigatie overslaan
Deel I Hoofdstuk 2

JavaScript

Hero image of the Web Almanac characters cycling to power a website.

Inleiding

JavaScript heeft een lange weg afgelegd sinds zijn bescheiden oorsprong als de laatste van de drie web-hoekstenen, naast CSS en HTML. Tegenwoordig begint JavaScript een breed spectrum van de technische stack te infiltreren. Het is niet langer beperkt tot de cliëntzijde en het wordt een steeds populairdere keuze voor build-tools en server-side scripting. JavaScript sluipt ook zijn weg naar de CDN-laag dankzij edge computing-oplossingen.

Ontwikkelaars houden van wat JavaScript. Volgens het hoofdstuk Opmaak is het script -element het 6e meest populaire HTML-element dat in gebruik is (vóór elementen zoals p en i, naast talloze andere). We besteden er ongeveer 14 keer zoveel bytes aan als aan HTML, de bouwsteen van het web, en 6 keer zoveel bytes als CSS.

Figuur 2.1. Mediane paginagewicht per inhoudstype.

Maar niets is gratis, en dat geldt vooral voor JavaScript - al die code heeft een prijs. Laten we eens kijken hoeveel script we gebruiken, hoe we het gebruiken en wat de gevolgen zijn.

Hoeveel JavaScript gebruiken we?

We zeiden dat de script-tag het 6e meest gebruikte HTML-element is. Laten we wat dieper graven om te zien hoeveel JavaScript dat eigenlijk is.

De gemiddelde site (het 50e percentiel) verzendt 444 KB JavaScript wanneer deze op een desktopapparaat wordt geladen, en iets minder (411 KB) naar een mobiel apparaat.

Figuur 2.2. Verdeling van het aantal geladen JavaScript-kilobytes per pagina.

Het valt een beetje tegen dat er hier geen grotere kloof is. Hoewel het gevaarlijk is om te veel aannames te doen over netwerk- of verwerkingskracht op basis van of het gebruikte apparaat een telefoon of een desktop is (of ergens tussenin), is het vermeldenswaard dat HTTP Archive mobiele tests worden gedaan door een Moto G4 en een 3G-netwerk te emuleren. Met andere woorden, als er werk werd verzet om zich aan te passen aan minder dan ideale omstandigheden door minder code door te geven, zouden deze tests dat moeten laten zien.

De trend lijkt ook in het voordeel te zijn van het gebruik van meer JavaScript, niet minder. In vergelijking met de resultaten van vorig jaar, zien we bij de mediaan een toename van 13,4% in JavaScript zoals getest op een desktopapparaat, en een 14,4% toename van de hoeveelheid JavaScript die naar een mobiel apparaat wordt verzonden.

cliënt 2019 2020 Verandering
Desktop 391 444 13,4%
Mobile 359 411 14,4%
Figuur 2.3. Jaar-op-jaar verandering in het mediaan aantal JavaScript-kilobytes per pagina.

Een deel van dit gewicht lijkt in ieder geval niet nodig te zijn. Als we kijken naar een uitsplitsing van hoeveel van dat JavaScript ongebruikt is bij het laden van een bepaalde pagina, zien we dat de mediaanpagina 152 KB ongebruikt JavaScript verzendt. Dat aantal springt naar 334 KB op het 75e percentiel en 567 KB op het 90e percentiel.

Figuur 2.4. Verdeling van de hoeveelheid verspilde JavaScript-bytes per mobiele pagina.

Als onbewerkte cijfers, kunnen die al dan niet naar u uitspringen, afhankelijk van hoeveel u van prestatie houdt, maar als u ernaar kijkt als een percentage van het totale JavaScript dat op elke pagina wordt gebruikt, wordt het een beetje gemakkelijker om te zien hoeveel afval we sturen.

37.22%
Figuur 2.5. Percentage van de mediaan JavaScript-bytes van de mobiele pagina dat niet wordt gebruikt.

Die 153 KB komt overeen met ~ 37% van de totale scriptgrootte die we naar mobiele apparaten verzenden. Er is hier zeker ruimte voor verbetering.

module en nomodule

Een van de mechanismen die we hebben om de hoeveelheid code die we naar beneden sturen mogelijk te verminderen, is om te profiteren van het module / nomodule patroon. Met dit patroon maken we twee sets bundels: één bundel bedoeld voor moderne browsers en één bedoeld voor oudere browsers. De bundel bedoeld voor moderne browsers krijgt een type=module en de bundel bedoeld voor oudere browsers krijgt een type=nomodule.

Met deze benadering kunnen we kleinere bundels maken met moderne syntaxis die zijn geoptimaliseerd voor de browsers die dit ondersteunen, terwijl we voorwaardelijk geladen polyfills en verschillende syntaxis bieden aan de browsers die dat niet doen.

Ondersteuning voor module en nomodule wordt steeds breder, maar nog relatief nieuw. Als gevolg hiervan is de acceptatie nog steeds een beetje laag. Slechts 3,6% van de mobiele pagina’s gebruikt ten minste één script met type=module en slechts 0,7% van de mobiele pagina’s gebruikt ten minste één script met type=nomodule om oudere browsers te ondersteunen.

Aantal aanvragen

Een andere manier om te kijken hoeveel JavaScript we gebruiken, is door te kijken hoeveel JavaScript-verzoeken er op elke pagina worden gedaan. Hoewel het verminderen van het aantal verzoeken van cruciaal belang was om goede prestaties te behouden met HTTP/1.1, is met HTTP/2 het tegenovergestelde het geval: JavaScript opsplitsen in kleinere, individuele bestanden is doorgaans beter voor prestaties.

Figuur 2.6. Verdeling van JavaScript-verzoeken per pagina.

Bij de mediaan doen pagina’s 20 JavaScript-verzoeken. Dat is slechts een kleine stijging ten opzichte van vorig jaar, toen de mediaanpagina 19 JavaScript-verzoeken deed.

Figuur 2.7. Verdeling van JavaScript-verzoeken per pagina in 2019.

Waar komt het vandaan?

Een trend die waarschijnlijk bijdraagt aan de toename van JavaScript dat op onze pagina’s wordt gebruikt, is het schijnbaar steeds groter wordende aantal scripts van derden dat aan pagina’s wordt toegevoegd om te helpen met alles, van A/B-tests en analyses aan de cliëntzijde tot het weergeven van advertenties en omgaan met personalisatie.

Laten we daar een beetje op ingaan om te zien hoeveel script van derden we serveren.

Tot aan de mediaan gebruiken sites ongeveer hetzelfde aantal eerste partij scripts als scripts van derden. Bij de mediaan zijn 9 scripts per pagina eerste partij, vergeleken met 10 per pagina van derden. Vanaf daar wordt de kloof een beetje groter: hoe meer scripts een site in het totaal gebruikt, hoe waarschijnlijker het is dat de meerderheid van die scripts afkomstig is van externe bronnen.

Figuur 2.8. Verdeling van het aantal JavaScript-verzoeken per host voor desktop.
Figuur 2.9. Verdeling van het aantal JavaScript-verzoeken per host voor mobiel.

Hoewel het aantal JavaScript-verzoeken vergelijkbaar is bij de mediaan, wordt de werkelijke grootte van die scripts iets zwaarder gewogen (bedoelde woordspeling) ten opzichte van bronnen van derden. De gemiddelde site stuurt 267 KB JavaScript van derden naar desktopapparaten, vergeleken met 147 KB van eerste partijen. De situatie is vergelijkbaar op mobiele apparaten, waar de mediaan-site 255 KB aan scripts van derden verzendt, vergeleken met 134 KB aan eigen scripts.

Figuur 2.10. Verdeling van het aantal JavaScript-bytes per host voor desktop.
Figuur 2.11. Verdeling van het aantal JavaScript-bytes per host voor mobiel.

Hoe laden we ons JavaScript?

De manier waarop we JavaScript laden, heeft een aanzienlijke invloed op de algehele ervaring.

JavaScript is standaard parser-blokkerend. Met andere woorden, wanneer de browser een script-element ontdekt, moet hij het ontleden van de HTML pauzeren totdat het script is gedownload, ontleed en uitgevoerd. Het is een aanzienlijk knelpunt en een veelvoorkomende oorzaak van pagina’s die traag worden weergegeven.

We kunnen beginnen met het compenseren van een deel van de kosten van het laden van JavaScript door scripts asynchroon te laden (met het async-attribuut), waardoor de HTML-parser alleen wordt gestopt tijdens de ontleed- en uitvoeringsfase en niet tijdens de downloadfase, of uitgesteld (met het defer-attribuut), wat de HTML-parser helemaal niet stopt. Beide attributen zijn alleen beschikbaar op externe scripts; inline scripts kunnen ze niet laten toepassen.

Op mobiele apparaten omvatten externe scripts 59,0% van alle gevonden scriptelementen.

Even terzijde: toen we het hadden over hoeveel JavaScript eerder op een pagina is geladen, hield dat totaal geen rekening met de grootte van deze inline scripts - omdat ze deel uitmaken van het HTML-document, worden ze meegeteld bij de opmaak-grootte . Dit betekent dat we nog meer script laden dat de cijfers laten zien.

Figuur 2.12. Verdeling van het aantal externe en inline scripts per mobiele pagina.

Van die externe scripts wordt slechts 12,2% geladen met het async-attribuut en 6,0% ervan wordt geladen met het defer-attribuut.

Figuur 2.13. Verdeling van het aantal async en defer-scripts per mobiele pagina.

Gezien het feit dat defer ons de beste laadprestaties biedt (door ervoor te zorgen dat het downloaden van het script parallel met ander werk gebeurt, en de uitvoering wacht tot nadat de pagina kan worden weergegeven), hopen we dat dit percentage iets hoger ligt. In feite is die 6,0% lichtjes opgeblazen.

Toen het ondersteunen van IE8 en IE9 vaker voorkwam, was het relatief gebruikelijk om allebei de async- en defer-attributen te gebruiken. Met beide attributen op hun plaats, zal elke browser die beide ondersteunt async gebruiken. IE8 en IE9, die async niet ondersteunen, vallen terug op defer.

Tegenwoordig is het patroon voor de overgrote meerderheid van de sites niet nodig en elk script dat met het patroon wordt geladen, zal de HTML-parser onderbreken wanneer deze moet worden uitgevoerd, in plaats van uit te stellen totdat de pagina is geladen. Het patroon wordt nog steeds verrassend vaak gebruikt, met 11,4% van de mobiele pagina’s die ten minste één script met dat patroon weergeven. Met andere woorden, ten minste enkele van de 6% van de scripts die defer gebruiken, profiteren niet van de volledige voordelen van het defer-attribuut.

There is an encouraging story here, though.

Harry Roberts tweette over het antipatroon op Twitter, wat ons ertoe aanzette om te kijken hoe vaak dit in het wild voorkwam. Rick Viscomi controleerde wie de grootste boosdoeners waren, en het blijkt dat “stats.wp.com” de bron was van de meest voorkomende overtreders. @Kraft van Automattic antwoordde, en het patroon wordt nu in de toekomst verwijderd.

Een van de geweldige dingen aan de openheid van het web is hoe één observatie kan leiden tot betekenisvolle verandering en dat is precies wat hier gebeurde.

Hulpbronnenhints

Een ander hulpmiddel dat we tot onze beschikking hebben om een deel van de netwerkkosten voor het laden van JavaScript te compenseren, zijn hulpbronnenhints, in het bijzonder prefetch en preload.

Met de prefetch-hint kunnen ontwikkelaars aangeven dat een bron zal worden gebruikt bij de volgende paginanavigatie, daarom moet de browser proberen om het te downloaden wanneer de browser niet actief is.

De preload-hint geeft aan dat een bron op de huidige pagina zal worden gebruikt en dat de browser deze meteen met een hogere prioriteit moet downloaden.

In totaal zien we 16,7% van de mobiele pagina’s die ten minste één van de twee bronhints gebruiken om JavaScript proactiever te laden.

Daarvan is bijna al het gebruik afkomstig van preload. Terwijl 16,6% van de mobiele pagina’s ten minste één preload hint gebruikt om JavaScript te laden, gebruikt slechts 0,4% van de mobiele pagina’s ten minste één prefetch-hint.

Er is een risico, vooral bij preload, dat er te veel hints worden gebruikt en de effectiviteit ervan wordt verminderd, dus het is de moeite waard om naar de pagina’s te kijken die deze hints gebruiken om te zien hoeveel ze gebruiken.

Figuur 2.14. Verdeling van het aantal prefetch-hints per pagina met eventuele prefetch-hints.
Figuur 2.15. Verdeling van het aantal preload-hints per pagina met eventuele preload-hints.

Bij de mediaan gebruiken pagina’s die een prefetch-hint gebruiken om JavaScript te laden er drie, terwijl pagina’s die een preload-hint gebruiken er slechts één gebruiken. De lange staart wordt een beetje interessanter, met 12 prefetch-hints gebruikt op het 90e percentiel en 7 preload-hints die ook op de 90e worden gebruikt. Voor meer informatie over hulpbronnenhints, bekijk het hoofdstuk Hulpbronnenhints van dit jaar.

Hoe serveren we JavaScript?

Zoals met elke op tekst gebaseerde bron op internet, kunnen we een aanzienlijk aantal bytes besparen door middel van minimalisatie en compressie. Dit zijn geen van beide nieuwe optimalisaties - ze bestaan al een tijdje - dus we zouden verwachten dat ze in meer gevallen worden toegepast dan niet.

Een van de audits in Lighthouse controleert op niet-geminimaliseerd JavaScript en geeft een score (0,00 is de slechtste, 1,00 is de beste) op basis van de bevindingen.

Figuur 2.16. Verdeling van niet-verkleinde JavaScript Lighthouse-auditscores per mobiele pagina.

De bovenstaande grafiek laat zien dat de meeste geteste pagina’s (77%) een score van 0,90 of hoger halen, wat betekent dat er maar weinig niet-verkleinde scripts worden gevonden.

In totaal is slechts 4,5% van de geregistreerde JavaScript-verzoeken niet geminimaliseerd.

Interessant is dat, hoewel we een beetje hebben gekozen voor verzoeken van derden, dit een gebied is waar scripts van derden het beter doen dan scripts van eersten. 82% van de gemiddelde niet-verkleinde JavaScript-bytes van een mobiele pagina is afkomstig van eigen code.

Figuur 2.17. Gemiddelde distributie van niet-verkleinde JavaScript-bytes per host.

Compressie

Minificatie is een geweldige manier om de bestandsgrootte te helpen verkleinen, maar compressie is nog effectiever en daarom belangrijker: het levert vaker wel dan niet het grootste deel van de netwerkbesparingen op.

Figuur 2.18. Verdeling van het percentage JavaScript-verzoeken per compressiemethode.

Bij 85% van alle JavaScript-verzoeken is een bepaald niveau van netwerkcompressie toegepast. Gzip maakt het grootste deel daarvan uit, met 65% van de scripts waarop Gzip-compressie is toegepast, vergeleken met 20% voor Brotli (br). Hoewel het percentage van Brotli (dat effectiever is dan Gzip) laag is in vergelijking met de browserondersteuning, gaat het in de goede richting, met een stijging van 5 procentpunten in het afgelopen jaar.

Nogmaals, dit lijkt een gebied te zijn waar scripts van derden het eigenlijk beter doen dan eerste partij scripts. Als we de compressiemethoden uitsplitsen door eerste en derde partij, zien we dat 24% van de scripts van derden Brotli heeft toegepast, vergeleken met slechts 15% van de scripts van eersten.

Figuur 2.19. Verdeling van het percentage mobiele JavaScript-verzoeken per compressiemethode en host.

Scripts van derden worden ook het minst waarschijnlijk zonder enige compressie aangeboden: 12% van de scripts van derden heeft noch Gzip noch Brotli toegepast, vergeleken met 19% van de eerste partij scripts.

Het is de moeite waard om die scripts die geen compressie hebben van naderbij te bekijken. Compressie wordt efficiënter in termen van besparingen naarmate het meer inhoud moet gebruiken. Met andere woorden, als het bestand klein is, wegen de kosten voor het comprimeren van het bestand soms niet op tegen de minuscule verkleining van de bestandsgrootte.

90,25%
Figuur 2.20. Percentage niet-gecomprimeerde JavaScript-verzoeken van derden onder 5 KB.

Gelukkig is dat precies wat we zien, vooral in scripts van derden, waar 90% van de niet-gecomprimeerde scripts minder dan 5 KB groot is. Aan de andere kant is 49% van de niet-gecomprimeerde eerste partij scripts minder dan 5 KB en 37% van de ongecomprimeerde eerste partij scripts groter dan 10 KB. Dus hoewel we veel kleine niet-gecomprimeerde eerste partij scripts zien, zijn er nog steeds een flink aantal die baat zouden hebben bij enige compressie.

Wat gebruiken we?

Omdat we steeds meer JavaScript hebben gebruikt om onze sites en applicaties van stroom te voorzien, is er ook een toenemende vraag naar open-source bibliotheken en frameworks om de productiviteit van ontwikkelaars en de algehele onderhoudbaarheid van de code te verbeteren. Sites die niet een van deze hulpmiddelen gebruiken, zijn beslist de minderheid op het internet van vandaag - jQuery alleen is te vinden op bijna 85% van de mobiele pagina’s die worden bijgehouden door HTTP Archive.

Het is belangrijk dat we kritisch nadenken over de hulpmidellen die we gebruiken om het web te bouwen en wat de afwegingen zijn, dus het is logisch om goed te kijken naar wat we vandaag in gebruik zien.

Bibliotheken

HTTP Archive gebruikt Wappalyzer om technologieën te detecteren die op een bepaalde pagina worden gebruikt. Wappalazyer houdt zowel JavaScript-bibliotheken bij (zie deze als een verzameling fragmenten of helperfuncties om de ontwikkeling te vergemakkelijken, zoals jQuery) en JavaScript-frameworks (dit zijn waarschijnlijker steigers en bieden sjablonen en structuur, zoals React).

De populaire bibliotheken die in gebruik zijn, zijn grotendeels ongewijzigd ten opzichte van vorig jaar, waarbij jQuery het gebruik blijft domineren en slechts één van de 21 beste bibliotheken valt uit (lazy.js, vervangen door DataTables). Zelfs de percentages van de topbibliotheken zijn nauwelijks veranderd ten opzichte van vorig jaar.

Figuur 2.21. Overname van de beste JavaScript-frameworks en -bibliotheken als percentage van de pagina’s.

Vorig jaar stelde Houssein een paar redenen voor waarom de dominantie van jQuery voortduurt:

WordPress, dat op meer dan 30% van de sites wordt gebruikt, bevat standaard jQuery. Het overschakelen van jQuery naar een nieuwere cliëntzijde bibliotheek kan enige tijd duren, afhankelijk van hoe groot een applicatie is, en veel sites kunnen bestaan uit jQuery naast nieuwere cliëntzijde bibliotheken.

Beide zijn zeer goede gissingen, en het lijkt erop dat de situatie op geen van beide fronten veel is veranderd.

In feite wordt de dominantie van jQuery nog verder ondersteund als u bedenkt dat van de top 10 bibliotheken er 6 jQuery zijn of jQuery nodig hebben om te kunnen worden gebruikt: jQuery UI, jQuery Migrate, FancyBox, Lightbox en Slick.

Frameworks

Als we naar de frameworks kijken, zien we ook niet veel van een dramatische verandering in termen van adoptie in de belangrijkste frameworks die vorig jaar naar voren kwamen. Vue.js heeft een aanzienlijke toename gezien en AMP is een beetje gegroeid, maar de meeste zijn min of meer waar ze een jaar geleden waren.

Het is vermeldenswaard dat het detectieprobleem dat vorig jaar werd opgemerkt nog steeds van toepassing is, en nog steeds van invloed is op de resultaten hier. Het is mogelijk dat er een aanzienlijke verandering in populariteit is opgetreden voor nog een paar van deze hulpmddelen, maar we zien het gewoon niet met de manier waarop de gegevens momenteel worden verzameld.

Wat het allemaal betekent

Interessanter voor ons dan de populariteit van de hulpmiddelen zelf is de impact die ze hebben op de dingen die we bouwen.

Ten eerste is het vermeldenswaard dat hoewel we misschien denken aan het gebruik van de ene hulpmiddel in plaats van de andere, we in werkelijkheid zelden slechts één enkele bibliotheek of framework gebruiken bij de productie. Slechts 21% van de geanalyseerde pagina’s rapporteert slechts één bibliotheek of framework. Twee of drie frameworks komen vrij vaak voor, en de lange staart wordt erg lang, erg snel.

Als we kijken naar de veel voorkomende combinaties die we in de productie zien, zijn de meeste te verwachten. Gezien de dominantie van jQuery, is het niet verwonderlijk dat de meeste populaire combinaties jQuery en een willekeurig aantal jQuery-gerelateerde plug-ins bevatten.

Combinaties Pagina’s (%)
jQuery 1.312.601 20,7%
jQuery, jQuery Migrate 658.628 10,4%
jQuery, jQuery UI 289.074 4,6%
Modernizr, jQuery 155.082 2,4%
jQuery, jQuery Migrate, jQuery UI 140.466 2,2%
Modernizr, jQuery, jQuery Migrate 85.296 1,3%
FancyBox, jQuery 84.392 1,3%
Slick, jQuery 72.591 1,1%
GSAP, Lodash, React, RequireJS, Zepto 61.935 1,0%
Modernizr, jQuery, jQuery UI 61.152 1,0%
Lightbox, jQuery 60.395 1,0%
Modernizr, jQuery, jQuery Migrate, jQuery UI 53.924 0,8%
Slick, jQuery, jQuery Migrate 51.686 0,8%
Lightbox, jQuery, jQuery Migrate 50.557 0,8%
FancyBox, jQuery, jQuery UI 44.193 0,7%
Modernizr, YUI 42.489 0,7%
React, jQuery 37.753 0,6%
Moment.js, jQuery 32.793 0,5%
FancyBox, jQuery, jQuery Migrate 31.259 0,5%
MooTools, jQuery, jQuery Migrate 28.795 0,5%
Figuur 2.22. De meest populaire combinaties van bibliotheken en frameworks op mobiele pagina’s.

We zien ook een behoorlijk aantal meer “moderne” frameworks zoals React, Vue en Angular in combinatie met jQuery, bijvoorbeeld als gevolg van migratie of opname door derden.

Combinatie Zonder jQuery Met jQuery
GSAP, Lodash, React, RequireJS, Zepto 1,0%  
React, jQuery   0,6%
React 0,4%  
React, jQuery, jQuery Migrate   0,4%
Vue.js, jQuery   0,3%
Vue.js 0,2%  
AngularJS, jQuery   0,2%
GSAP, Hammer.js, Lodash, React, RequireJS, Zepto 0,2%  
Eindtotaal 1,7% 1,4%
Figuur 2.23. De meest populaire combinaties van React, Angular en Vue met en zonder jQuery.

Wat nog belangrijker is, al deze hulpmiddelen betekenen doorgaans meer code en meer verwerkingstijd.

Als we specifiek naar de gebruikte frameworks kijken, zien we dat de mediaan JavaScript-bytes voor pagina’s die deze gebruiken, enorm variëren, afhankelijk van wat wordt gebruikt.

De onderstaande grafiek toont de mediaan bytes voor pagina’s waar een van de top 35 meest gedetecteerde frameworks is gevonden, uitgesplitst naar cliënt.

Figuur 2.24. Het gemiddelde aantal JavaScript-kilobytes per pagina door JavaScript-framework.

Op één van de spectrums staan frameworks zoals React of Angular of Ember, die de neiging hebben om veel code te verzenden, ongeacht de cliënt. Aan de andere kant zien we minimalistische frameworks zoals Alpine.js en Svelte veelbelovende resultaten laten zien. Standaarden zijn erg belangrijk, en het lijkt erop dat Svelte en Alpine er allebei in slagen (tot dusver… is de steekproefomvang vrij klein) om een lichtere set pagina’s te creëren door te beginnen met zeer performante standaarden.

We krijgen een vergelijkbaar beeld als we kijken naar de hoofdthread-tijd voor pagina’s waarop deze hulpmiddelen zijn gedetecteerd.

Figuur 2.25. De mediane hoofdthread-tijd per pagina door JavaScript-framework.

Ember’s mobiele hoofdthread-tijd springt eruit en vervormt de grafiek enigszins met hoe lang het duurt. (Ik heb hier wat meer tijd aan besteed en het lijkt sterk beïnvloed te worden door een bepaald platform dat dit framework inefficiënt gebruikt, in plaats van een onderliggend probleem met Ember zelf). Door het eruit te trekken, wordt de afbeelding een beetje gemakkelijker te begrijpen.

Figuur 2.26. De mediane hoofdthread-tijd per pagina door JavaScript-framework, met uitzondering van Ember.js.

Hulpmiddelen zoals React, GSAP en RequireJS besteden vaak veel tijd aan de hoofdthread van de browser, ongeacht of het een desktop- of mobiele paginaweergave is. Dezelfde hulpmiddelen die in het algemeen tot minder code leiden - hulpmiddelen zoals Alpine en Svelte - hebben ook de neiging om de impact op de hoofdthread te verkleinen.

De kloof tussen de ervaring die een framework biedt voor desktop en mobiel, is ook de moeite waard om in te graven. Mobiel verkeer wordt steeds dominanter en het is van cruciaal belang dat onze hulpmiddelen zo goed mogelijk presteren voor mobiele paginaweergaven. Hoe groter de kloof die we zien tussen desktop- en mobiele prestaties voor een framework, hoe groter de rode vlag.

Figuur 2.27. Verschil tussen de mediaan van de hoofdthread-tijd voor desktop en mobiel per pagina volgens JavaScript-framework, met uitzondering van Ember.js.

Zoals u zou verwachten, is er een gat voor alle gebruikte hulpmiddelen vanwege de lagere verwerkingskracht van de geëmuleerde Moto G4. Ember en Polymer lijken eruit te springen als bijzonder flagrante voorbeelden, terwijl hulpmiddelen zoals RxJS en Mustache slechts in geringe mate variëren van desktop tot mobiel.

Wat is de impact?

We hebben nu een redelijk goed beeld van hoeveel JavaScript we gebruiken, waar het vandaan komt en waarvoor we het gebruiken. Hoewel dat op zichzelf al interessant genoeg is, is de echte kicker de “so what?” Welke impact heeft al dit script eigenlijk op de beleving van onze pagina’s?

Het eerste dat we moeten overwegen, is wat er gebeurt met al dat JavaScript nadat het is gedownload. Downloaden is slechts het eerste deel van de JavaScript-reis. De browser moet nog steeds al dat script ontleden, compileren en uiteindelijk uitvoeren. Hoewel browsers constant op zoek zijn naar manieren om een deel van die kosten over te dragen aan andere threads, gebeurt veel van dat werk nog steeds op de hoofdthread, waardoor de browser wordt geblokkeerd om lay-out- of verfgerelateerd werk te doen, en ook om te kunnen reageren op gebruikersinteractie.

Als u zich herinnert, was er slechts een verschil van 30 KB tussen wat naar een mobiel apparaat wordt verzonden en een desktopapparaat. Afhankelijk van uw standpunt, zou het u kunnen worden vergeven dat u niet al te boos bent over het kleine verschil in de hoeveelheid code die naar een desktopbrowser wordt verzonden versus een mobiele browser - wat is tenslotte ongeveer 30 KB extra bij de mediaan?

Het grootste probleem ontstaat wanneer al die code wordt geserveerd op een low-to-middle-end apparaat, iets minder dan het soort apparaten dat de meeste ontwikkelaars waarschijnlijk hebben, en een beetje meer het soort apparaten dat u zult zien van de meerderheid van de mensen over de hele wereld. Die relatief kleine kloof tussen desktop en mobiel is veel dramatischer als we ernaar kijken in termen van verwerkingstijd.

De gemiddelde desktopsite besteedt 891 ms aan de hoofdthread van een browser die met al dat JavaScript werkt. De gemiddelde mobiele site besteedt echter 1897 ms, meer dan twee keer de tijd die op de desktop wordt doorgebracht. Het is zelfs nog erger voor de lange staart van sites. Op het 90e percentiel besteden mobiele sites maar liefst 8.921 ms aan hoofdthread-tijd aan JavaScript, vergeleken met 3.838 ms voor desktopsites.

Figuur 2.28. Verdeling van de hoofdthread-tijd.

Het correleren van JavaScript-gebruik met Lighthouse-scores

Een manier om te zien hoe dit zich vertaalt in het beïnvloeden van de gebruikerservaring, is door te proberen een aantal JavaScript-statistieken die we eerder hebben geïdentificeerd te correleren met Lighthouse-scores voor verschillende statistieken en categorieën.

Figuur 2.29. Correlaties van JavaScript op verschillende aspecten van gebruikerservaring.

De bovenstaande grafiek gebruikt de Pearson correlatiecoëfficiënt. Er is een lange, nogal complexe definitie van wat dat precies betekent, maar de kern is dat we zoeken naar de sterkte van de correlatie tussen twee verschillende getallen. Als we een coëfficiënt van 1,00 vinden, hebben we een directe positieve correlatie. Een correlatie van 0,00 zou geen verband tussen twee getallen aantonen. Alles onder de 0,00 duidt op een negatieve correlatie - met andere woorden, als het ene getal stijgt, neemt het andere af.

Ten eerste lijkt er niet echt een meetbare correlatie te bestaan tussen onze JavaScript-statistieken en de Lighthouse-score voor toegankelijkheid (“LH A11y” in de grafiek) hier. Dat staat in schril contrast met wat elders is gevonden, met name via het jaarlijkse onderzoek van WebAim.

De meest waarschijnlijke verklaring hiervoor is dat de toegankelijkheidstests van Lighthouse (nog!) Niet zo uitgebreid zijn als wat beschikbaar is via andere hulpmiddelen, zoals WebAIM, die toegankelijkheid als hun primaire focus hebben.

Waar we wel een sterke correlatie zien, is tussen het aantal JavaScript-bytes (“Bytes”) en zowel de algehele prestatie van Lighthouse (“LH Perf”) score als de Total Blocking Time (“TBT”).

De correlatie tussen JavaScript-bytes en de prestatiescores van Lighthouse is -0,47. Met andere woorden, naarmate JS-bytes toenemen, nemen de prestatiescores van Lighthouse af. De totale bytes hebben een sterkere correlatie dan het aantal bytes van derden (“3P bytes”), wat erop duidt dat hoewel ze zeker een rol spelen, we niet alle schuld bij derden kunnen leggen.

Het verband tussen de totale blokkeringstijd en JavaScript-bytes is zelfs nog belangrijker (0,55 voor totale bytes, 0,48 voor bytes van derden). Dat is niet zo verwonderlijk, gezien wat we weten over al het werk dat browsers moeten doen om JavaScript op een pagina te laten werken - meer bytes betekent meer tijd.

Beveiligingskwetsbaarheden

Een andere nuttige audit die Lighthouse uitvoert, is om te controleren op bekende beveiligingsproblemen in bibliotheken van derden. Het doet dit door te detecteren welke bibliotheken en frameworks op een bepaalde pagina worden gebruikt en welke versie van elk wordt gebruikt. Vervolgens controleert het Snyk’s open-source kwetsbaarheidsdatabase om te zien welke kwetsbaarheden zijn ontdekt in de geïdentificeerde hulpmiddelen.

83,50%
Figuur 2.30. Het percentage mobiele pagina’s bevat ten minste één kwetsbare JavaScript-bibliotheek.

Volgens de audit gebruikt 83,5% van de mobiele pagina’s een JavaScript-bibliotheek of -framework met minstens één bekende beveiligingslek.

Dit is wat we het jQuery-effect noemen. Weet u nog hoe we zagen dat jQuery op maar liefst 83% van de pagina’s wordt gebruikt? Verschillende oudere versies van jQuery bevatten bekende kwetsbaarheden, die de overgrote meerderheid van de kwetsbaarheden omvatten die deze audit controleert.

Van de ongeveer 5 miljoen mobiele pagina’s waartegen wordt getest, bevat 81% een kwetsbare versie van jQuery - een aanzienlijke voorsprong op de tweede meest gevonden kwetsbare bibliotheek - jQuery UI met 15,6%.

Bibliotheek Kwetsbare pagina’s
jQuery 80,86%
jQuery UI 15,61%
Bootstrap 13,19%
Lodash 4,90%
Moment.js 2,61%
Handlebars 1,38%
AngularJS 1,26%
Mustache 0,77%
Dojo 0,58%
jQuery Mobile 0,53%
Figuur 2.31. Top 10 bibliotheken die volgens Lighthouse bijdragen aan het hoogste aantal kwetsbare mobiele pagina’s.

Met andere woorden, als we mensen zover kunnen krijgen om weg te migreren van die verouderde, kwetsbare versies van jQuery, zouden we het aantal sites met bekende kwetsbaarheden zien dalen (tenminste, totdat we er enkele in de nieuwere frameworks beginnen te vinden).

Het merendeel van de gevonden kwetsbaarheden valt in de categorie “gemiddeld”.

Figuur 2.32. Verdeling van het percentage mobiele pagina’s met JavaScript-kwetsbaarheden naar ernst.

Gevolgtrekking

JavaScript wordt gestaag populair, en daar is veel positiefs over. Het is ongelooflijk om te bedenken wat we dankzij JavaScript op het internet van vandaag kunnen bereiken, dat zelfs een paar jaar geleden onvoorstelbaar zou zijn geweest.

Maar het is duidelijk dat we ook voorzichtig moeten zijn. De hoeveelheid JavaScript stijgt elk jaar consequent (als de aandelenmarkt zo voorspelbaar was, zouden we allemaal ongelooflijk rijk zijn), en dat komt met afwegingen. Meer JavaScript is verbonden met een toename van de verwerkingstijd, wat een negatief effect heeft op belangrijke statistieken zoals de totale blokkeringstijd. En als we die bibliotheken laten wegkwijnen zonder ze actueel te houden, lopen ze het risico gebruikers bloot te stellen aan bekende beveiligingsproblemen.

Een zorgvuldige afweging van de kosten van de scripts die we aan onze pagina’s toevoegen en bereid zijn om onze hulpmiddelen kritisch in de gaten te houden en er meer van te vragen, zijn onze beste weddenschappen om ervoor te zorgen dat we een web bouwen dat toegankelijk, performant en veilig is.

Auteur

Citaat

BibTeX
@inbook{WebAlmanac.2020.JavaScript,
author = "Kadlec, Tim en Alam, Sawood en Denysov, Artem en Viscomi, Rick en Calvano, Paul",
title = "JavaScript",
booktitle = "De 2020 Web Almanac",
chapter = 2,
publisher = "HTTP Archive",
year = "2020",
language = "Nederlands",
url = "https://almanac.httparchive.org/en/2020/javascript"
}