När det gäller prestanda på webben handlar det om att göra så lite som möjligt direkt när sidan laddar och att ladda in rätt resurser vid rätt tillfälle. Med standardtekniker går det att utveckla hållbara och snabba webbsidor utan onödig kod.

I denna artikel kommer jag gå igenom fem nya tekniker för att förbättra prestandan på en webbsida. Några av dessa går bra att använda redan idag medan andra är experimentella men kan vara bra att vara förberedd på inför framtida bruk. De här teknikerna kan användas för att ladda in rätt resurser vid rätt tillfälle och förbättra resultat för Google Core Web Vitals.

De fem teknikerna är:

Loading-attributet

Loading-attributet avgör om resurser som bilder, videor eller iframes ska laddas direkt eller om de ska laddas in vid ett senare tillfälle när de blir synliga på skärmen. Det har tidigare vanligtvis gjorts med JavaScript men det kan innebära en del problem som exempelvis att HTML-koden inte validerar, beroende av JavaScript för att visa bilder samt att extra kod måste laddas in och köras.

Nu finns det en standardteknik för detta i och med loading-attributet. Enligt specifikationen kan två olika värden användas för att ge instruktioner till webbläsare om hur en resurs ska laddas:

  • lazy: som ber webbläsaren att vänta med att ladda resursen tills senare.
  • eager: som berättar för webbläsaren att resursen ska laddas direkt.

Den mest intressanta av dessa värden är lazy. Genom att ange loading=lazy på bild-element så väntar webbläsaren med att ladda in dessa bilder om de inte syns på skärmen när sidan laddar. De laddas in först när användaren scrollar på sidan och bilderna börjar närma sig den synliga delen av skärmen. Enligt HTTP-archives statistik står bilder för mer än 40% av den data som laddas in när en användare besöker en webbsida. Om vissa av dessa bilder ligger utanför den synliga delen av skärmen är det en stor prestandaförbättring att vänta med att ladda in bilderna eftersom de eventuellt inte kommer att visas.

Så här enkelt är det att lägga till lazy loading av bilder:

<img src="cat.gif" alt="" loading="lazy">

Webbläsarstöd

Loading-attributet fungerar idag i de flesta moderna webbläsare förutom Safari, som dock verkar få stöd för det inom kort.

Äldre webbläsare kommer ignorera attributet och ladda in alla bilder som vanligt. Därmed är det full möjligt att använda attributet idag.

Mer info om Loading-attributet

Specifikation av Loading-attributet
Artikel om lazy loading av Web.dev

Resource Hints

Resource Hints är en teknik för att förbereda resurser innan de används. En webbplats upplevda prestanda kan förbättras om det i förtid går att förutse vilka resurser som behövs direkt och vilka som kan laddas in senare.

Resource Hints används med link-elementet i webbsidans head-element och kan användas för att ansluta till en annan tjänst, ladda eller till och med rendera en sida i förväg.

Följande värden finns att använda:

DNS prefetch

När en internetadress anropas behöver en så kallad DNS lookup göras. Kortfattat kan man säga att det är ett steg när en domännamnsserver gör en översättning av ett domännamn (t.ex metamatrix.se) till ett IP-nummer (t.ex 13.79.2.71) som används av en server.

Om en webbsida laddar in resurser från en annan domän behöver en DNS lookup göras för varje domän som anropas. Vanliga exempel på detta är att det laddas in JavaScript-kod från en webbanalystjänst eller bilder från ett Content Delivery Network (CDN).

Eftersom varje DNS lookup tar lite tid kan DNS-prefetch användas för att uppmana webbläsaren att förbereda detta i bakgrunden så att när resursen anropas är en DNS lookup redan utförd.

Exempel på DNS-prefetch:

<link rel="dns-prefetch" href="https://cdn.website.com">

Preconnect

Preconnect gör samma sak som DNS-prefetch men förbereder också en anslutning till servern. Det är inte helt lätt att skilja på när det är lämpligt att använda preconnect eller DNS-prefetch men preconnect gör mer arbete och är mer krävande. Det skadar sällan att använda preconnect om man är säker på att en anslutning kommer att ske.

Exempel på preconnect:

<link rel="preconnect" href="https://cdn.website.com">

Prefetch

Gör samma sak som preconnect men laddar också ner och cachear resursen i webbläsaren. 

Exempel på preconnect:

<link rel="prefetch" href="https://cdn.website.com/toppbild.jpg">

Preload

Preload gör samma sak som prefetch. Skillnaden är att prefetch ber webbläsaren att ladda ner en resurs men det är upp till webbläsaren att avgöra när det ska göras. Preload säger åt webbläsaren att den ska ladda ner resursen med en hög prioritering. En tumregel kan vara att preload används för resurser som behövs direkt för att visa sidan medan prefetch används för resurser som behövs senare.

Ett vanligt exempel på när preload används är för att förhandsladda resurser som länkas in i CSS-filer så som bilder eller typsnitt. Typsnitt kan laddas in på lite olika sätt men ett exempel på vad som sker är när ett typsnitt ska användas på en webbsida är:

  1. Sidans HTML-kod laddas ner.
  2. HTML-koden tolkas av webbläsaren.
  3. En inlänkad CSS-fil hittas i HTML-koden.
  4. CSS-filen laddas ner.
  5. CSS-koden tolkas av webbläsaren.
  6. En inlänkad typsnittsfil hittas i CSS-koden.
  7. Typsnittsfilen laddas ner.
  8. Webbsidan är klar att visas.

Det kan leda till att det tar tid att ladda in webbsidan då webbläsaren måste vänta på att alla resurser som behövs för att visa sidan ska ladda klart eller att texten flimrar till när typsnittet laddats in och byts ut på sidan. För att undvika detta kan man ladda in typsnittsfilen i bakgrunden i förväg med preload och på så sätt flytta steg 7 upp till steg 3. När CSS-koden tolkas och texten på sidan visas har typsnittsfilen redan laddats in helt eller delvis. Tiden det tar att visa webbsidan kan på så vis snabbas upp.

Preload har även fler attribut som kan användas:

  • as: Anger vilken typ resursen är t.ex script eller style och en korrekt Content Security Policy kan tillämpas för resursen.
  • type: Anger vilken MIME type resursen är. Om en webbläsare inte har stöd för typen kan den låta bli att ladda ner resursen i onödan.
  • crossorigin: Anger vilka regler som gäller för att hämta resurser från andra domäner.

Exempel på preload av typsnittsfil:

<link rel="preload" href="font.woff" as="font" type="font/woff" crossorigin>

Prerender

Prerender gör samma sak som prefetch men ber också webbläsaren att tolka och rendera HTML-kod för en webbsida. Om användare går igenom ett registreringsformulär med flera sidor och alla användare ska gå igenom alla steg kan det vara lämpligt att göra en prerender av nästa sida så att den redan finns förberedd när användaren klickar på knappen för att gå till nästa steg.  

Exempel på prerender:

<link rel="prerender" href="sida2.html"> 

Webbläsarstöd

Resource Hints har bra stöd i webbläsare idag och ignoreras av äldre webbläsare. De går bra att använda idag för att ge en snabbare upplevelse till moderna webbläsare utan att skapa problem för äldre webbläsare.

Mer info om Resource Hints

Specifikation av Resource Hints
Artikel om Resource Hints av Addy Osmani
Smashing Magazine-artikel om Resource Hints

Content Visibility

Content-visibility är en CSS-egenskap för att styra om HTML-element ska visas på sidan. Den kan ha tre olika värden: 

  • visible: som är standardvärdet.
  • hidden: som kan liknas med CSS-egenskapen display: none.
  • auto: som överlämnar ansvaret till webbläsaren och är det intressanta av värdena. 

Genom att ange content-visibilty: auto för HTML-element kan vi be webbläsaren att vänta med att beräkna och rita ut dessa element tills det är nödvändigt, till exempel om de ligger långt ner på sidan och användaren scrollar neråt så att de blir synliga på skärmen. På så vis kommer sidan att ladda snabbare direkt eftersom mindre tid behöver läggas på att beräkna utseende för och rita ut innehåll som inte är synligt på skärmen.

Ett exempel är en startsida som är uppdelad i flera olika section-element:

section {
    content-visibility: auto;
    contain-intrinsic-size: 0 500px;
}

Eftersom innehållet som ännu inte har ritats ut inte är synligt och därmed inte har någon höjd kan sidans scrollbar förändras allt eftersom sidans delar ritas ut. För att motverka detta finns en annan CSS-egenskap för att ange ett elements egentliga storlek: contain-intrinsic-size. Det påverkar inte elementets riktiga höjd utan ger bara webbläsaren information om hur stort elementet förväntas vara.

Webbläsarstöd

Content-visibilty har idag stöd i webbläsarna Edge, Chrome och Opera. Äldre webbläsare kommer ignorera egenskapen och den kan därmed användas idag utan för att förbättra prestanda i moderna webbläsare utan att skapa problem i äldre webbläsare.

Mer info om Content Visibility

Specifikation av Content Visibility
Web.dev-artikel om Content Visibility

Client Hints

Client Hints är en ny teknik för att med HTTP headers kunna skicka med information om den enhet som används till servern. Det går bland annat att skicka med information om skärmstorlek, bilders verkliga visningsstorlek hur mycket minne som finns tillgängligt på användarens enhet och vilken uppkopplingshastighet de har.

Ett exempel på när detta skulle vara användbart är för responsiva bilder. Istället för att generera flera olika versioner av en bild i förväg och låta webbläsaren avgöra vilken bild som ska visas kan servern välja ett lämpligt bildformat utifrån enhetens egenskaper. Den stora fördelen med Client Hints i detta fall är att vi kan presentera olika innehåll beroende på användarens uppkopplingshastighet vilket inte varit möjligt att göra tidigare med en standardteknik.

Exempel på Client Hints headers för bilders bredd och hastighet på uppkoppling i form av megabits per sekund (downlink):

Accept-CH: Width, Downlink

Om användaren har en liten skärm och en långsam uppkoppling kan servern skicka en väl komprimerad jpeg-bild. Om användaren istället har en stor skärm, en snabb uppkoppling och en webbläsare med stöd för webp-bilder kan servern skicka en högupplöst, okomprimerad webp-bild.

För responsiva bilder skulle det leda till mycket enklare kod. 

Istället för:

<picture>
 <source srcset="liten.webp 320w,
     mellan.webp 640w,
     stor.webp 1024w"
     type="image/webp">
 <img sizes="100vw" srcset="liten.jpg 320w,
     mellan.jpg 640w,
     stor.jpg 1024w"
     src="liten.jpg" 
     alt="" />
</picture>

Kan det se ut liknande:

<img src="bild.jpg" sizes="100vw" alt="" />

// Exempel pseudokod på server
string format = Headers["Accept"] == "image/webp" ? "webp" : "jpg";
int compressionLevel = Headers["Downlink"] > 1 ? 90 : 60;
int imageWidth = Headers["Width"];
return GenerateImage(fileName, format, compressionLevel, imageWidth);

Webbläsarstöd

Client hints fungerar idag delvis i webbläsarna Chrome, Edge och Opera. Det är fullt möjligt att använda idag och leverera en standardversion istället för en optimerad version till äldre webbläsare. Men det finns fortfarande en stor andel webbläsare som inte kommer dra nytta av att använda Client Hints.

Mer info om Client Hints

Specifikation av Client Hints
Google Developers-artikel om Client Hints

Priority Hints

Historiskt så har webbläsare laddat in innehåll på webbsidor i den ordning de ligger i HTML-koden. En Stylesheet eller JavaScript-fil som ligger i sidans head-element laddas in före en bild som ligger i sidans body-element. Moderna webbläsare försöker dock själva göra en prioritering av hur sidans olika delar ska laddas in. Stylesheet och typsnitts-filer får då oftast hög prioritering eftersom de påverkar sidans utseende och behöver laddas in snabbt. 

Du kan själv se vilken prioritet en resurs har i Google Chrome på Network-fliken i Developer Tools. Priority visas inte som standard men går att visa genom att högerklicka på kolumnrubrikerna och välja att visa Priority.

Ofta gör webbläsaren ett bra jobb med att prioritera men ibland kan utvecklare behöva bestämma prioriteringen själva. Priority Hints är en ny teknik för att lösa detta. För att sätta prioritering används attributet importance i HTML-koden på script, img, link eller iframe-element. Här är ett exempel:

<img src="bild.jpg" alt="" importance="high">

Importance-attributet kan ha följande tre värden:

  • High: Webbläsaren instrueras att prioritera inladdningen av resursen högt.
  • Low: Webbläsaren instrueras att prioritera inladdningen av resursen lågt.
  • Auto: Låt webbläsaren prioritera. Detta är standardvärdet.

Ett exempel på när importance-attributet är användbart är för karusell-komponenter där bara den första "sliden" är synlig och användaren klickar för att visa övriga slides. Det är då möjligt att berätta för webbläsaren att den första bilden i karusellen är viktigast att ladda in.

<div class="carousel">
    <div class="carousel-item"><img src="bild1.jpg" importance="high" alt=""></div>
    <div class="carousel-item"><img src="bild2.jpg" importance="low" alt=""></div>
    <div class="carousel-item"><img src="bild3.jpg" importance="low" alt=""></div>
</div>

Webbläsarstöd

Priority Hints är fortfarande en experimentell teknik. För tillfället är det bara Google Chrome som har stöd för Priority Hints. Det går att använda idag men det ger troligen ingen större effekt då det bara är en webbläsare som har stöd för tekniken. Det är heller inte en officiell standard ännu vilket gör att den kan komma att förändras med tiden.

Mer info om Priority Hints

Specifikation av Priority Hints
Artikel om Priority Hints av Google Developers

Sammanfattning

De olika teknikerna går att använda i kombination för att skapa en snabbare och bättre användarupplevelse. Loading-attributet är ett bra exempel på en standardteknik som är superenkel att använda sig av och ger stor effekt. Med loading-attributet och content-visibility går det att fördröja inladdning av innehåll som inte ligger på den synliga delen av sidan när den laddas. Resource Hints kan användas för att priritera inladdning av innehåll som är synligt direkt när sidan laddas. Enligt mig är dock Client Hints den kanske mest spännande tekniken för att optimera vilka resurser som ska levereras till användaren. Med relativt liten insats går det att optimera storleken på resurser beroende på användarens uppkopplingshastighet.