14 metoder for å utsette eller planlegge JavaScript
Lær hvordan du utsetter og planlegger JavaScript

Hvorfor utsette eller planlegge JavaScript?
JavaScript kan (og vil) bremse ned nettstedet ditt på flere måter. Dette kan ha alle slags negative konsekvenser for Core Web Vitals. JavaScript kan konkurrere om nettverksressurser, det kan konkurrere om CPU- ressurser (blokkere hovedtråden) og det kan til og med blokkere parsingen av en nettside. Å utsette og planlegge skriptene dine kan drastisk forbedre Core Web Vitals.
Table of Contents!
- Hvorfor utsette eller planlegge JavaScript?
- Hvordan kan JavaScript-timing påvirke Core Web Vitals?
- Hvordan velge riktig utsettelsesmetode?
- Metode 1: Bruk defer-attributtet
- Metode 2: Bruk async-attributtet
- Metode 3: Bruk moduler
- Metode 4: Plasser skript nær bunnen av siden
- Metode 5: Injiser skript
- Metode 6: Injiser skript på et senere tidspunkt
- Metode 7: Endre skripttypen (og endre den tilbake igjen)
- Metode 9: Bruk readystatechange
- Metode 10: Bruk setTimeout uten timeout
- Metode 11: Bruk setTimeout med en timeout
- Metode 12: Bruk et promise for å sette en mikro-oppgave
- Metode 13: Bruk en mikro-oppgave
- Metode 15: Bruk postTask
For å minimere de negative effektene som JavaScript kan ha på Core Web Vitals, er det vanligvis en god idé å spesifisere når et skript blir satt i kø for nedlasting og planlegge når det kan bruke CPU-tid og blokkere hovedtråden.
Hvordan kan JavaScript-timing påvirke Core Web Vitals?
Hvordan kan JavaScript-timing påvirke Core Web Vitals? Ta bare en titt på dette eksempelet fra virkeligheten. Den første siden er lastet med «renderingsblokkerende» JavaScript. Paint-metrikene samt Time to interactive er ganske dårlige. Det andre eksempelet er av nøyaktig den samme siden, men med JavaScript utsatt. Du vil se at LCP-bildet fortsatt fikk et stort slag. Det tredje eksempelet har det samme skriptet utført etter sidens «load event» og har funksjonskallene brutt opp i mindre deler. Denne siste passerer Core Web Vitals med god margin.



Som standard vil ekstern JavaScript i head-delen av siden blokkere oppbyggingen av render- treet. Mer spesifikt: når nettleseren møter et skript i dokumentet, må den pause DOM-konstruksjonen, gi kontrollen over til JavaScript-kjøretiden, og la skriptet kjøre før den fortsetter med DOM-konstruksjonen. Dette vil påvirke Paint-metrikene dine (Largest Contentful Paint og First Contentful Paint).
Utsatt eller asynkron JavaScript kan fortsatt påvirke paint-metrikene, spesielt Largest Contentful Paint fordi det vil kjøres, og blokkere hovedtråden, når DOM-en er opprettet (og vanlige LCP-elementer som kanskje ikke har blitt lastet ned).
Eksterne JavaScript-filer vil også konkurrere om nettverksressurser. Eksterne JavaScript-filer lastes vanligvis ned tidligere enn bilder. HVIS du laster ned for mange skript, vil nedlastingen av bildene dine bli forsinket.
Sist, men ikke minst, kan JavaScript blokkere eller forsinke bruker- interaksjon. Når et skript bruker CPU-ressurser (blokkerer hovedtråden) vil en nettleser ikke reagere på input (klikk, scrolling osv.) før skriptet er fullført.
Hvordan fikser planlegging eller utsettelse av JavaScript Core Web Vitals?
Hvordan velge riktig utsettelsesmetode?
Ikke alle skript er like, og hvert skript har sin egen funksjonalitet. Noen skript er viktige å ha tidlig i renderingsprosessen, andre er det ikke.

Jeg liker å kategorisere JavaScripts i 4 grupper basert på hvor viktige de er.
1. Renderingskritisk. Dette er skriptene som vil endre utseendet til en nettside. Hvis de ikke lastes, vil ikke siden se komplett ut. Disse skriptene bør unngås for enhver pris. Hvis du ikke kan unngå dem av en eller annen grunn, bør de ikke utsettes. For eksempel en toppslider eller et A/B-testingskript.
2. Kritisk. Disse skriptene vil ikke endre utseendet til en nettside (for mye), men siden vil ikke fungere bra uten dem. Disse skriptene bør utsettes eller kjøres asynkront. For eksempel menyskirptene dine.
3. Viktig. Dette er skript du vil laste fordi de er verdifulle for deg eller besøkende. Jeg pleier å laste disse skriptene etter at load- eventen har blitt utløst. For eksempel analytics eller en «tilbake til toppen»-knapp.
4. Kjekt å ha. Dette er skript du kan klare deg uten hvis du absolutt må. Jeg laster disse skriptene med lavest mulig prioritet og kjører dem kun når nettleseren er inaktiv. For eksempel en chat-widget eller en Facebook-knapp.
Metode 1: Bruk defer-attributtet
Skript med defer-attributtet vil lastes ned parallelt og legges til i defer JavaScript- køen. Rett før nettleseren utløser DOMContentLoaded-eventen vil alle skriptene i den køen kjøres i den rekkefølgen de vises i dokumentet.
<script src='javascript.js'></script> «Defer-trikset» fikser vanligvis mange problemer, spesielt paint-metrikene. Dessverre er det ingen garanti, det avhenger av kvaliteten på skriptene. Utsatte skript vil kjøres når alle skriptene er lastet ned og HTML-en er parset (DOMContentLoaded). LCP-elementet (vanligvis et stort bilde) er kanskje ikke lastet innen da, og de utsatte skriptene vil fortsatt forårsake en forsinkelse i LCP.
Når bør du bruke dette:
Bruk utsatte skript for kritiske skript som trengs så snart som mulig.
Fordeler:
- Utsatte skript vil lastes ned parallelt
- DOM-en vil være tilgjengelig ved kjøretidspunktet
Ulemper:
- Utsatte skript kan forsinke LCP-metrikene dine
- Utsatte skript vil blokkere hovedtråden når de kjøres
- Det er kanskje ikke trygt å utsette skript når inline- eller asynkrone skript er avhengige av dem
Metode 2: Bruk async-attributtet
Skript med async-attributtet lastes ned parallelt og vil kjøres umiddelbart etter at de er ferdig nedlastet.
<script src='javascript.js'></script> Asynkrone skript vil gjøre lite for å fikse pagespeed-problemene dine. Det er flott at de lastes ned parallelt, men det er omtrent det. Når de er lastet ned, vil de blokkere hovedtråden mens de kjøres.
Når bør du bruke dette:
Bruk asynkrone skript for kritiske skript som trengs så snart som mulig og er selvstendige (ikke avhengige av andre skript).
Fordeler:
- Asynkrone skript vil lastes ned parallelt.
- Asynkrone skript vil kjøres så snart som mulig.
Ulemper:
- DOMContentLoaded kan skje både før og etter asynkrone skript.
- Kjørerekkefølgen til skriptene vil være ukjent på forhånd.
- Du kan ikke bruke asynkrone skript som er avhengige av andre asynkrone eller utsatte skript
Metode 3: Bruk moduler
Modulære skript er utsatt som standard med mindre de har async-attributtet. I så fall vil de bli behandlet som asynkrone skript
<script src='javascript.js'></script> Moduler er en ny måte å tenke om JavaScript på og fikser noen designfeil. Utover det vil bruk av skript- moduler ikke gjøre nettstedet ditt raskere.
Når bør du bruke dette:
Når applikasjonen din er bygget på en modulær måte, gir det mening å også bruke JavaScript-moduler.
Fordeler:
- Moduler er utsatt som standard
- Moduler er enklere å vedlikeholde og fungerer utmerket med modulær webdesign
- Moduler tillater enkel kodeoppdeling med dynamiske importer der du kun importerer modulene du trenger til en bestemt tid.
Ulemper:
- Moduler i seg selv vil ikke forbedre Core Web Vitals
- Å importere moduler just-in-time eller på sparket kan være tregt og forverre FID og INP
Metode 4: Plasser skript nær bunnen av siden
Footer-skript settes i kø for nedlasting på et senere tidspunkt. Dette vil prioritere andre ressurser som er i dokumentet over script-taggen.
<html>
<head></head>
<body>
[your page contents here]
<script defer src='javascript.js'></script>
</body>
</html> Å plassere skriptene dine nederst på siden er en interessant teknikk. Dette vil planlegge andre ressurser (som bilder) foran skriptene dine. Dette vil øke sjansen for at de er tilgjengelige for nettleseren og malt på skjermen før JavaScript-filene er ferdig nedlastet og hovedtråden vil bli blokkert av skriptkjøring. Likevel ... ingen garanti.
Når bør du bruke dette:
Når skriptene dine allerede presterer ganske bra, men du vil prioritere andre ressurser som bilder og webfonter litt høyere.
Fordeler:
- Å plassere skript nederst på siden krever ikke mye kunnskap.
- Hvis det gjøres riktig, er det ingen risiko for at dette vil ødelegge siden din
Ulemper:
- Kritiske skript kan bli lastet ned og kjørt senere
- Det fikser ikke underliggende JavaScript-problemer
Metode 5: Injiser skript
Injiserte skript behandles som asynkrone skript. De lastes ned parallelt og kjøres umiddelbart etter nedlasting.
<script>
const loadScript = (scriptSource) => {
const script = document.createElement('script');
script.src = scriptSource;
document.head.appendChild(script);
}
// call the loadscript function that injects 'javascript.js'
loadScript('javascript.js');
</script> Fra et Core Web Vitals-perspektiv er denne teknikken nøyaktig det samme som å bruke <script async>.
Når bør du bruke dette:
Denne metoden brukes ofte av tredjepartsskript som utløses så tidlig som mulig. Funksjonskallet gjør det enkelt å innkapsle og komprimere kode.
Fordeler:
- Innkapslet kode som injiserer et asynkront skript.
Ulemper:
- DOMContentLoaded kan skje både før og etter at skriptet er lastet.
- Kjørerekkefølgen til skriptene vil være ukjent på forhånd.
- Du kan ikke bruke dette på skript som er avhengige av andre asynkrone eller utsatte skript
Metode 6: Injiser skript på et senere tidspunkt
Kjekt-å-ha-skript bør etter min mening aldri lastes utsatt. De bør injiseres på det mest gunstige tidspunktet. I eksempelet nedenfor vil skriptet kjøres etter at nettleseren har sendt «load»-eventen.
<script>
window.addEventListener('load', function () {
// see method 5 for the loadscript function
loadScript('javascript.js');
});
</script> Dette er den første teknikken som pålitelig vil forbedre Largest Contentful Paint. Alle viktige ressurser, inkludert bilder, vil være lastet ned når nettleseren utløser «load event». Dette kan introdusere alle slags problemer fordi det kan ta lang tid før load-eventen blir kalt.
Når bør du bruke dette:
For kjekt-å-ha-skript som ikke har noen grunn til å påvirke paint-metrikene.
Fordeler:
- Vil ikke konkurrere om kritiske ressurser fordi skriptet injiseres når siden og dens ressurser er lastet
Ulemper:
- Hvis siden din er dårlig designet med tanke på Core Web Vitals, kan det ta lang tid før siden sender «load»-eventen
- Du må være forsiktig med å ikke bruke dette på kritiske skript (som lazy loading, meny osv.)
Metode 7: Endre skripttypen (og endre den tilbake igjen)
Hvis en script-tagg finnes et sted på siden som 1. har et type-attributt og 2. type- attributtet ikke er "text/javascript", vil skriptet ikke bli lastet ned og kjørt av en nettleser. Mange JavaScript-lastere (som CloudFlares RocketLoader) baserer seg på dette prinsippet. Ideen er ganske enkel og elegant.
Først skrives alle skript om til dette:
<script src="javascript.js"></script> Deretter, på et tidspunkt under lasteprosessen, konverteres disse skriptene tilbake til «vanlige JavaScripts».
Når bør du bruke dette:
Dette er ikke en metode jeg ville anbefalt. Å fikse JavaScript-påvirkning krever mye mer enn bare å flytte hvert skript litt lenger ned i køen. På den annen side, hvis du har lite kontroll over skriptene som kjører på siden eller har utilstrekkelig JavaScript-kunnskap, kan dette være ditt beste alternativ.
Fordeler:
- Det er enkelt, bare aktiver Rocket Loader eller en annen plugin, og alle skriptene dine kjøres nå på et noe senere tidspunkt.
- Det vil sannsynligvis fikse paint-metrikene dine, forutsatt at du ikke brukte JS-basert lazy loading.
- Det vil fungere for inline og eksterne skript.
Ulemper:
- Du vil ikke ha finkornet kontroll over når skriptene kjøres
- Dårlig skrevne skript kan gå i stykker
- Det bruker JavaScript for å fikse JavaScript
- Det gjør ingenting for å fikse langvarige skript
Metode 8: Bruk intersection observer
Med intersection observer kan du kjøre en funksjon (som i dette tilfellet laster et eksternt JavaScript) når et element scroller inn i det synlige viewporten.
<script>
const handleIntersection = (entries, observer) => {
if (entries?.[0].isIntersecting) {
// load your script or execute another
function like trigger a lazy loaded element
loadScript('javascript.js');
// remove the observer
observer.unobserve(entries?.[0].target);
}
};
const Observer = new window.IntersectionObserver()
Observer.observe(document.querySelector('footer'));
</script> Dette er uten tvil den mest effektive metoden for å utsette JavaScript. Last bare inn skriptene du trenger, rett før du trenger dem. Dessverre er virkeligheten sjelden så ryddig, og ikke mange skript kan knyttes til et element som scroller inn i visningen.
Når bør du bruke dette:
Bruk denne teknikken så mye som mulig! Når et skript kun samhandler med en komponent utenfor skjermen (som et kart, en slider, et skjema), er dette den beste måten å injisere skriptet på.
Fordeler:
- Vil ikke forstyrre Core Web Vitals LCP og FCP
- Vil aldri injisere skript som ikke brukes. Dette vil forbedre FID og INP
Ulemper:
- Bør ikke brukes med komponenter som kan være i det synlige viewporten
- Er vanskeligere å vedlikeholde enn enkel <script src="...">
- Kan introdusere et Cumulative Layout Shift
Metode 9: Bruk readystatechange
document.readystate kan brukes som et alternativ til «DOMContentloaded»- og «load»-eventen. Den «interactive» readystate er vanligvis et godt sted å kalle kritiske skript som trenger å endre DOM-en eller legge til hendelsesbehandlere.
Den «complete» readystate er et godt sted å kalle skript som er mindre kritiske.
document.addEventListener('readystatechange', (event) => {
if (event.target.readyState === 'interactive') {
initLoader();
} else if (event.target.readyState === 'complete') {
initApp();
}
}); Metode 10: Bruk setTimeout uten timeout
setTimeout er en uglesett, men sterkt undervurdert metode i pagespeed-miljøet. setTimeout har fått et dårlig rykte fordi det ofte misbrukes. Mange utviklere tror setTimeout bare kan brukes til å forsinke skriptkjøring med det angitte antall millisekunder. Selv om dette stemmer, gjør setTimeout faktisk noe mye mer interessant. Det oppretter en ny oppgave på slutten av nettleserens event loop. Denne oppførselen kan brukes til å planlegge oppgavene dine effektivt. Det kan også brukes til å bryte opp lange oppgaver i separate mindre oppgaver
<script>
setTimeout(() => {
// load a script or execute another function
console.log('- I am called from a 0ms timeOut()')
}, 0);
console.log('- I was last in line but executed first')
/*
Output:
- I was last in line but executed first
- I am called from a 0ms timeOut()
*/
</script> Når bør du bruke dette:
setTimeout oppretter en ny oppgave i nettleserens event loop. Bruk dette når hovedtråden din blokkeres av mange funksjonskall som kjøres sekvensielt.
Fordeler:
- Kan bryte opp langvarig kode i mindre deler.
Ulemper:
- setTimeout er en ganske grov metode og tilbyr ikke prioritering for viktige skript.
- Vil legge koden som skal kjøres på slutten av loopen
Metode 11: Bruk setTimeout med en timeout
Ting blir enda mer interessant når vi kaller setTimeout med en timeout på mer enn 0 ms
<script>
setTimeout(() => {
// load a script or execute another function
console.log('- I am called from a 10ms timeOut()')
}, 10);
setTimeout(() => {
// load a script or execute another function
console.log('- I am called from a 0ms timeOut()')
}, 0);
console.log('- I was last in line but executed first')
/*
Output:
- I was last in line but executed first
- I am called from a 0ms timeOut()
- I am called from a 10ms timeOut()
*/
</script> Når bør du bruke dette:
Når du trenger en enkel metode for å planlegge ett skript etter et annet, vil en liten timeout gjøre susen
Fordeler:
- Støttes i alle nettlesere
Ulemper:
- Tilbyr ikke avansert planlegging
Metode 12: Bruk et promise for å sette en mikro-oppgave
Å opprette en mikro-oppgave er også en interessant måte å planlegge JavaScript på. Mikro-oppgaver er planlagt for kjøring umiddelbart etter at den nåværende kjøreløkken er fullført.
<script>
const myPromise = new Promise((resolve, reject) => {
resolve();
}).then(
() => {
console.log('- I was scheduled after a promise')
}
);
console.log('- I was last in line but executed first')
/*
Output:
- I was last in line but executed first
- I was scheduled after a promise
*/
</script> Når bør du bruke dette:
Når en oppgave må planlegges umiddelbart etter en annen oppgave.
Fordeler:
- Mikro-oppgaven vil bli planlagt umiddelbart etter at oppgaven er ferdig med å kjøre.
- En mikro-oppgave kan brukes til å forsinke mindre viktige deler av JavaScript-kode i samme event.
Ulemper:
- Vil ikke bryte opp hovedtråden i mindre deler. Nettleseren vil ikke ha mulighet til å reagere på brukerinput.
- Du vil sannsynligvis aldri trenge å bruke mikro-oppgaver for å forbedre Core Web Vitals med mindre du allerede vet nøyaktig hva du gjør.
Metode 13: Bruk en mikro-oppgave
Det samme resultatet kan oppnås ved å bruke queueMicrotask(). Fordelen med å bruke queueMicrotask() fremfor et promise er at det er litt raskere og du trenger ikke å håndtere promises.
<script>
queueMicrotask(() => {
console.log('- I am a microtask')
})
console.log('- I was last in line but executed first')
/*
Output:
- I was last in line but executed first
- I am a microtask
*/
</script> Metode 14: Bruk requestIdleCallback
Metoden window.requestIdleCallback() setter en funksjon i kø som skal kalles under nettleserens inaktive perioder. Dette gjør det mulig for utviklere å utføre bakgrunns- og lavprioritetsarbeid på hoved-event- loopen, uten å påvirke latensfølsomme hendelser som animasjon og inputrespons. Funksjoner kalles vanligvis i først-inn-først-ut-rekkefølge; men tilbakekall som har en timeout angitt kan bli kalt i annen rekkefølge om nødvendig for å kjøre dem før tidsfristen utløper.
<script>
requestIdleCallback(() => {
const script = document.createElement('script');
script.src = 'javascript.js';
document.head.appendChild(script);
});
</script> Når bør du bruke dette:
Bruk dette for skript som er kjekt å ha, eller for å håndtere ikke-kritiske oppgaver etter brukerinput
Fordeler:
- Kjør JavaScript med minimal påvirkning for brukeren
- Vil mest sannsynlig forbedre FID og INP
Ulemper:
- Støttes i de fleste nettlesere, men ikke alle. Det finnes poly-fills som faller tilbake på setTimeout();
- Ingen garanti for at koden noensinne vil kjøres
Metode 15: Bruk postTask
Metoden lar brukere valgfritt spesifisere en minimumsforsinkelse før oppgaven kjøres, en prioritet for oppgaven, og et signal som kan brukes til å endre oppgaveprioritet og/eller avbryte oppgaven. Den returnerer et promise som resolves med resultatet av oppgavens tilbakekallsfunksjon, eller rejectes med avbrytelsesårsaken eller en feil kastet i oppgaven.
<script>
scheduler.postTask(() => {
const script = document.createElement('script');
script.src = 'javascript.js';
document.head.appendChild(script);
}, { priority: 'background' });
</script> Når bør du bruke dette:
postTask er det perfekte API-et for å planlegge skript med. Dessverre er nettleserstøtten for øyeblikket dårlig, så du bør ikke bruke det.
Fordeler:
- Fullstendig kontroll over JavaScript-kjøreplanlegging!
Ulemper:
- Støttes ikke i noen viktige nettlesere.
CrUX data is 28 days late.
Google provides data 28 days late. CoreDash provides data in real-time. Debug faster.
- Real-Time Insights
- Faster Debugging
- Instant Feedback

