Det asynkrone skriptet i sidefeltet fungerer ikke. Best fungerende asynkron javascript-lasting

Merk: Nedenfor er en oversettelse av en artikkel fra Steve Souders (forfatter av de berømte Yahoo!-tipsene angående klientytelse) "Kobling av asynkrone skript". Steve analyserer lasteoppførselen til JavaScript-filer og foreslår flere måter å omgå blokkeringsegenskapene deres. Mine kommentarer nedenfor er i kursiv.

Det meste av arbeidet mitt er inne I det siste ble viet til asynkron lasting av eksterne skript. Hvis skript lastes inn i normal rekkefølge (), blokkerer de lasting av alle andre sidekomponenter ( V siste versjoner Dette er ikke tilfelle i Firefox og Safari, men vi snakker hovedsakelig om 70 % av IE-brukerne) og blokker gjengivelsen av hele delen av siden som ligger under kallet til skriptene i HTML-koden. Dette kan sees på testsiden, vi plasserer skriptene under for eksempel ved å bruke dynamisk skapelse objekter etter at det kombinerte hendelsesvinduet.onload utløses) forhindrer denne nettleseroppførselen, noe som øker hastigheten på sidelasting.

Det eneste problemet med å laste skript asynkront er deres interaksjon med interne ( på linje) sideskript ( så vel som med andre eksterne skript), som bruker variabler definert i et eksternt skript. Hvis et eksternt skript lastes asynkront uten kunnskap om den interne koden til HTML-siden, er det ganske mulig at ( og det vil skje i de fleste tilfeller) når noen variabler ikke vil bli definert på tidspunktet for bruk. Derfor må du sørge for at eksterne skript lastet asynkront og interne sideskript er koblet sammen: interne skript kjøres ikke før asynkrone skript er fullstendig lastet.

Det er flere ( standard) måter å koble asynkront lastede skript med annen JavaScript-kode:

  • vindu pålasting. Kjøring av intern JavaScript-kode kan knyttes til vinduet onload-hendelsen. Det er veldig enkelt å bruke, men noen av skriptene kan kjøres tidligere.
  • onreadystatechange i skriptet. Den interne koden kan være bundet til onreadystatechange og/eller onload-hendelsene. (Det vil være nødvendig å bruke begge alternativene for å dekke alt populære nettlesere.) I dette tilfellet vil det være mer kode, det vil være mer komplekst, men det vil være en garanti for at det vil bli utført umiddelbart etter innlasting av de tilsvarende eksterne filene.
  • Innebygde samtaler. Eksterne skript kan endres for å inkludere helt på slutten et kall til en liten kodebit som vil kalle den tilsvarende funksjonen fra den interne koden. Alt dette er flott hvis eksterne og interne skript er utviklet av samme team. Men i tilfelle bruk av tredjepartsutviklinger, vil ikke dette gi all nødvendig fleksibilitet for å koble eksterne skript med intern kode.

I denne artikkelen dekker jeg samtidig (ingen ordspill!) to spørsmål: hvordan asynkrone skript øker hastigheten på sidelasting og hvordan du kan kombinere asynkrone skript og interne ved å bruke en modifisert versjon av lasteren fra John Resig ( av jQuery) er en dobbel skript-tagmal. En illustrasjon på dette er mitt siste arbeid med å sortere UA Profiler-resultater. Jeg gjorde det ved å bruke sorteringsskriptet fra Stuart Langridge. På omtrent 5 minutter var jeg i stand til å legge til manuset hans på en side for å sortere resultattabellen. Med litt mer tid klarte jeg å få dette skriptet til å lastes asynkront og øke hastigheten på sideinnlastingen med over 30 % ved å bruke den asynkrone skriptdokkingsteknikken.

Vanlige manusanrop

Jeg la opprinnelig Stuart Langridges sorteringsskript til UA Profiler-siden på vanlig måte(via ), dette kan sees i varianten med en vanlig script call. Lastediagrammet er vist i fig. 1.

Ris. 1. Diagram over lasting av skript i vanlig tilfelle.

Selv om sorteringen av dataene i tabellen fungerte, gjorde det meg ikke lykkeligere fordi sideinnlastingen gikk langsommere. I fig. 1 viser tydelig hvordan min versjon av skriptet (kalt sorttable-async.js) blokkerer alle andre HTTP-forespørsler på siden (spesielt arrow-right-20x9.gif), noe som bremser innlastingen av siden. Alle lastediagrammer ble tatt med Firebug 1.3 beta. I denne versjonen av Firebug viser den røde linjen onload-hendelsen. (Og den blå linjen tilsvarer den domcontentloaded-hendelsen.) For versjonen med et vanlig skriptkall, starter onload-hendelsen ved 487 millisekunder.

Sorttable-async.js-skriptet er ikke nødvendig for å gjengi siden først: kolonner kan bare sorteres etter at selve kolonnene er gjengitt. Denne situasjonen (eksterne skript som ikke brukes til å gjengi siden i utgangspunktet) er nummer 1-kandidaten for å implementere asynkron lasting. Alternativet med asynkron lasting av skript kobler sammen dette skriptet ved å bruke DOM-metoder for å lage et nytt script tag:

var script = document.createElement("script"); script.src = "sortable-async.js"; script.text = "sorttable.init()"; // dette er forklart i neste avsnitt document.getElementsByTagName("head").appendChild(script);

HTTP-lastingsdiagrammet for asynkron lasting av skript er vist i fig. 2. Det er verdt å merke seg hvordan den asynkrone tilnærmingen forhindrer blokkeringsadferd: sorttable-async.js og arrow-right-20x9.gif lastes inn parallelt. Dette reduserer Total tid lastetiden er 429 ms.

Ris. 2. Diagram over lasting av skript i det asynkrone tilfellet

Prøve dobbeltmanus av John Resig

Lar deg øke hastigheten på sideinnlastingen, men i dette tilfellet er det fortsatt rom for forbedringer. Som standard kaller sorteringsskriptet seg selv ved å legge til sorttable.init() til behandleren laste hendelser for dette manuset. Noen ytelsesforbedringer ( og kodereduksjon) kan oppnås ved å kalle sorttable.init() inne i en script-tag for å kalle den umiddelbart etter at det eksterne skriptet er lastet ( koblet til via src). I dette tilfellet bruker jeg en enkelt funksjon som "API", men jeg antar at dette tilfellet illustrerer et maksimalt utvidbart mønster som lar deg bruke ekstern modul uten noen forutsetninger om det videre bruk (klassisk situasjon med bruk av JavaScript-logikk fra eksterne utviklere).

Jeg har allerede beskrevet tre metoder for å koble intern kode med asynkron lasting av eksterne skript: vindu onload, onreadystatechange for skriptet og en behandler innebygd i skriptet. I stedet brukte jeg en teknikk fra John Resig – det doble script tag-mønsteret. John beskriver hvordan man kobler interne skript til lasting ekstern fil på følgende måte:

jQuery("p").addClass("pen");

I dette tilfellet utløses koden inne bare etter lasting ( og initialisering) eksternt skript er avsluttet. Denne skriptkoblingsmetoden har flere åpenbare fordeler:

  • enklere: én skripttag i stedet for to
  • mer gjennomsiktig: sammenhengen mellom intern og ekstern kode er mer åpenbar
  • sikrere: hvis det eksterne skriptet ikke lastes, vil den interne koden ikke bli utført, noe som vil forhindre at feil relatert til udefinerte variabler vises

Dette er et flott mønster for å laste eksterne skript asynkront. For å bruke den må vi imidlertid gjøre endringer i både den interne koden og den eksterne filen. For den interne koden måtte jeg legge til den tredje linjen som allerede er nevnt ovenfor, som avslører egenskapen script.text. For å fullføre dokkingsprosessen må du legge til sorttable-async.js til slutt:

var scripts = document.getElementsByTagName("script"); var cntr = scripts.length; while (cntr) ( var curScript = scripts; if (-1 != curScript.src.indexOf("sorttable-async.js")) ( eval(curScript.innerHTML); break; ) cntr--; )

Denne koden går gjennom alle skriptene på siden, finner den nødvendige blokken, som skal laste seg selv (i dette tilfellet er det et skript med en src som inneholder sorttable-async.js). Den kjører så koden som legges til skriptet (i dette tilfellet sorttable.init()) og kaller seg selv. (Liten merknad: selv om teksten i det ble lagt til ved lasting av skriptet ved hjelp av tekstegenskaper, åpnes den ved å bruke innerHTML-egenskapen. Dette er nødvendig for å sikre kompatibilitet på tvers av nettlesere.) Ved å bruke denne optimaliseringen kan vi laste inn en ekstern skriptfil uten å blokkere lasting av andre ressurser, og kjøre den som er koblet til dette manuset intern kode.

Det er også verdt å merke seg at den beskrevne teknikken bare kan være en erstatning for direkte modifikasjon av et eksternt skript. Hvis en slik modifikasjon ikke er mulig, kan vi bare bruke installasjonen av en lastkontroll med et intervall:

var _on_ready_execution = setInterval(function() (if (type urchinTracker === funksjon) ( urchinTracker(); clearInterval(_on_ready_execution); ) ), 10);

Denne tilnærmingen er allerede beskrevet i boken "Overklokke nettstedet ditt", men det innebærer ekstra belastning på prosessoren for konstant kontroll det nødvendige skriptet er klart og fungerer ikke hvis den eksterne filen er utilgjengelig: sjekken fortsetter å kjøre.

Men ved sjekk etter intervall trenger vi ikke å modifisere den eksterne filen i det hele tatt, men ved dobbel bruk av script-taggen er dette rett og slett nødvendig. Intervallkontroll kan forbedres hvis du, etter at det har gått en tid (for eksempel 5-10 sekunder), starter nedlastingen av den eksterne filen på nytt (endre den originale skriptkoden ved hjelp av en unik GET-parameter), og etter flere mislykkede omstarter stopper du laster ned helt (kanskje med noen så en feilmelding).

Lat lasting

Den totale lastetiden kan reduseres ytterligere ved å bruke " lat lasting» script (last det dynamisk som en del av onload-hendelsesbehandleren). Et eksempel på denne oppførselen finnes på siden med

Hilsen, venner! Visste du at lasting av JavaScript er en av de mest flaskehalser i nettstedets ytelse? I dag er hovedoppgaven min å forklare hva et skript er og hvordan det påvirker hastigheten og ytelsen til nettstedet.

En nettleser som laster inn en skriptkode, slutter å gjengi siden til skriptet er lastet inn og utført. Siden er blokkert og nettleseren reagerer ikke på brukerhandlinger på et par sekunder. Forsinkelsestiden avhenger av flere faktorer:

  • konfigurasjoner,
  • Internett-tilkoblingshastighet,
  • filstørrelse og andre...

Av denne grunn anbefaler Google PageSpeed ​​​​Insights nettstedhastighetsanalysator å fjerne fra toppen av siden JavaScript-kode, blokkerer visningen. En god praksis er å plassere skript nederst på siden, for eksempel før den avsluttende taggen eller sette opp asynkron lasting.

Hvis skriptkoden påvirker visningen av den øverste delen av nettstedet, ikke plasser den inn egen fil, og bygge inn direkte i HTML.

JS kan endre nettstedets innhold og til og med omdirigere til en annen URL. I dette tilfellet vil tilkobling av skriptet på slutten av dokumentet føre til effekten av å "rykke" siden, laste inn nye eller endre eksisterende elementer øverst.

Bruk av asynkron- og defer-attributtene på skript-taggen

La oss finne ut hva asynkront og utsatt arbeid i JavaScript er og hva den grunnleggende forskjellen er mellom asynkron- og defer-attributtene. Men først, la oss se på sekvensen for å behandle et dokument ved å bruke en vanlig skriptkode.

1 < src = "example.js" >

I klart eksempel Jeg vil bruke følgende symboler:

— sidebehandling
- script laster
— skriptutførelse

Dermed skjer behandlingssekvensen i henhold til følgende skjema:

Parsing av HTML-koden avbrytes mens skriptet lastes og kjøres, hvoretter det fortsetter. Det er en forsinkelse i visningen av nettsiden.

utsett attributt

Defer-attributtet lar nettleseren begynne å laste ned js-filer parallelt uten å stoppe videre behandling av siden. De henrettes etter full analyse objektmodell document (fra den engelske Document Object Model, forkortet DOM), mens nettleseren garanterer konsistens basert på rekkefølgen filene kobles til.

1 < defer src = "example.js" >

async attributt

Støtte for async-attributtet dukket opp i HTML5, det lar nettleseren laste ned js-filer parallelt og kjøre dem umiddelbart etter nedlasting, uten å vente på at resten av siden skal behandles.

1 < async src = "example.js" >

Behandlingssekvensdiagram:

Dette er en asynkron nedlasting. Dette attributtet anbefales for bruk i skript som ikke har en betydelig innvirkning på visningen av dokumentet. Disse inkluderer tellere for statistikkinnsamling ( Google Analytics, Yandex Metrica), annonseringsnettverkskoder (Yandex Advertising Network, Google AdSense), knapper sosiale nettverk og så videre.

Nettstedets lastehastighet er en av rangeringsfaktorene i Google.

Asynkron JavaScript-tilkobling reduserer sideinnlastingstid ved å eliminere ventetid. Sammen med dette anbefaler jeg å komprimere og slå sammen js-filer til én, for eksempel ved å bruke . Brukere liker raske sider 😎

Moderne nettsider er tungt lastet med javascript-filer. Dette fører til tregere lasting og påfølgende visning av siden. Under de verste forholdene må den besøkende vente opptil 30 sekunder.

Vi setter fart laster html sider

Moderne bruk av JavaScript

Moderne nettsider er tungt lastet med javascript-filer. Dette fører til tregere lasting og påfølgende visning av siden. Under de verste forholdene (langsom Internett-tilkobling, mange javascript-filer) en besøkende på nettstedet må vente opptil 30 sekunder.

HTML er utformet på en slik måte at en nettside laster ved å synkront (linje for linje) laste i sin tur alle elementene som er inkludert i HTML-koden.

Det er en løsning: sett Java-strengene på slutten html-dokument(derfor vil de bli lastet inn etter at hele siden er tegnet) og først etter det vil innholdet i blokkene vises i på de rette stedene. Det kalles .

Alle seriøse prosjekter i dag prøver å bytte til ny teknologi nedlastinger. Dessuten er det helt enkelt.

Det er flere tilnærminger. Jeg starter i rekkefølge.

< script src= "//www.site.ru/script.js" type= "text/javascript" >

HTML5-standarden støtter muligheten til å laste skript asynkront, noe som kan øke hastigheten på den totale siden for gjenfinning betydelig. Bare legg til asynkron eller utsett .

< script async src= "//www.site.ru/script.js" type= "text/javascript" >

< script defer src= "//www.site.ru/script.js" type= "text/javascript" >

Hva er forskjellen mellom asynkron- og defer-attributtene?

I begge tilfeller får vi asynkron lasting av skript. Den eneste forskjellen er øyeblikket når skriptet begynner å kjøre. Et skript med async-attributtet vil bli utført så snart som mulig etter det fullastet, men før vindusobjektet er lastet inn. Hvis defer-attributtet brukes, vil ikke skriptet bryte rekkefølgen for kjøringen i forhold til andre skript, og kjøringen vil skje etter at siden er fullstendig lastet og analysert, men før DOMContentLoaded-hendelsen til dokumentobjektet.

Dessverre fungerer ikke denne mekanismen for øyeblikket i alle nettlesere (spesielt IE). Fungerer heller ikke hvis det er document.write-linjer i script.js-filen.

Som alle eksperter vet, legger Google spesiell vekt på lastehastigheten til nettsteder og reduserer sakte. Søkeresultater. For å hjelpe har Google utviklet et spesielt skript som du kan gjøre asynkron javascript-lasting med.

For å bruke, bare bytt ut


Og koble til skriptfilen extsrc.js

Det vil bli slik:

< script src= "//extsrcjs.googlecode.com/svn/trunk/extsrc.js" > < script extsrc= "...." >

Denne metoden fungerer dessverre heller ikke for filer med document.write

En universell metode for alle nettlesere. Fungerer til og med med document.write

På stedet på siden der vi faktisk trenger å vise elementet vårt, lag en tom div-blokk:

< div id= "script_block" class = "script_block" >

Helt på slutten av siden, før vi setter inn et skript for asynkron lasting av filer:

< div id= "script_ad" class = "script_ad" style= "display:none;" >Her er alle filer eller skript som må lastes.< script type= "text/javascript" >// flytt den til reell stilling vise dokumentet. getElementById("script_block" ) . appendChild(dokument. getElementById("script_ad" ) ); // vis dokument. getElementById("script_ad" ) . stil. display = "blokk" ;

I de eldste versjonene av IE (6 og under) fungerer dessverre ikke asynkron lasting, men det er praktisk talt ingen slike brukere lenger. Alle andre nettlesere og tjenester bruker moderne akselerert lasting nettsider.

HTML er utformet på en slik måte at nettsiden lastes sekvensielt linje for linje, og laster på sin side alle elementene som er inkludert i html-koden. Og hvis en av dem er utilgjengelig (for eksempel, javaScript fra et eksternt nettsted leses ikke), stopper videre lasting av nettstedet.

Når uleselig JS er øverst på siden, kan den besøkende ikke se noe i det hele tatt.

Derfor, når du bruker JavaScript fra tredjepartssider på nettstedet ditt, for eksempel for å vise annonser, er det sterkt tilrådelig å laste dem asynkront. I dette tilfellet vil ikke tredjeparts JS forsinke lasting og visning av nettstedet ditt.

Dessverre ikke alle annonsenettverk gi muligheten til å laste skript asynkront. Derfor vil jeg i denne artikkelen fortelle deg hvordan du endrer synkron lastekode til asynkron. Hvis eieren av dette skriptet ikke gir dette alternativet.

Standard synkron JS-lasting

Vanligvis ser det slik ut å kalle et skript fra en ekstern server:

Asynkron skriptlasting som Google/Adsense gjør

Jeg fikk ideen fra Google/Adsense. For at skriptet skal lastes asynkront fra resten av HTML-koden, må du legge til asynkron i anropskoden.

Og nå for at koden skal lastes asynkront, bør skriptkallet vårt fra den eksterne serveren se slik ut:

Som du kan se, er alt enkelt. Riktignok vil dette bare fungere i nettlesere som støtter HTML5-standarden. På tidspunktet for skriving av denne artikkelen er det et absolutt flertall av slike nettlesere.

Det foreslåtte alternativet er ikke 100 % universelt. Mange skript slutter ganske enkelt å fungere etter å ha gjort disse endringene. I følge anmeldelser på Internett fungerer ikke denne metoden hvis elementet brukes i skriptet document.write.

Pålitelig asynkron lastealternativ

Hvis det første foreslåtte alternativet ikke fungerer for deg. Så dra nytte følgende anbefalinger. Dette er egentlig lat lasting. Siden den virkelige script-kallingen skjer helt på slutten HTML-sider, det vil si når alt nødvendig innhold på siden allerede er på skjermen.

På stedet på siden der du vil vise resultatet JavaScript fungerer du må lage en tom div-blokk:

På slutten av siden før den avsluttende BODY-taggen setter vi inn et skript for asynkron lasting:

// JavaScript som må lastes asynkront // flytt det til den faktiske visningsposisjonen document.getElementById("script_block_0").appendChild(document.getElementById("script_ad_0")); // show document.getElementById("script_ad_0").style.display = "blokk";

Hvis det er flere reklameblokker, må du for hver av dem gjenta alt og lage unike individuelle DIV-blokker. Ikke glem å endre klassenavn og DIV-ID. I mitt eksempel er det nok å endre tallet null, i den nye blokken må det erstattes med 1, og så videre.

Dette alternativet er mer komplekst, men det fungerer overalt bortsett fra svært eldgamle nettlesere som f.eks Internet Explorer 6. Som heldigvis nesten aldri finnes på brukernes datamaskiner.

Det er en vei ut: Plasser Javascript-linjene på slutten av html-dokumentet (derfor vil de bli lastet etter at hele siden er tegnet) og først etter det vil innholdet i blokkene vises på de riktige stedene. Det kalles . Alle seriøse prosjekter i dag prøver å bytte til ny lasteteknologi så raskt som mulig. Dessuten er det helt enkelt.

Det er flere tilnærminger. Jeg starter i rekkefølge.

script src= type= "tekst/javascript" >

Asynkron lasting av HTML5-skript

HTML5-standarden støtter muligheten til å laste skript asynkront, noe som kan øke hastigheten på den totale siden for gjenfinning betydelig. Bare legg til asynkron eller utsett .

< script async src= "http://www.site.ru/script.js" type= "text/javascript" >

< script defer src= "http://www.site.ru/script.js" type= "text/javascript" >

Hva er forskjellen mellom asynkron- og defer-attributtene?

I begge tilfeller får vi asynkron lasting av skript. Den eneste forskjellen er øyeblikket når skriptet begynner å kjøre. Et skript med async-attributtet vil bli utført så snart som mulig etter at det er fulllastet, men før vindusobjektet er lastet. Hvis defer-attributtet brukes, vil ikke skriptet bryte rekkefølgen for kjøringen i forhold til andre skript, og kjøringen vil skje etter at siden er fullstendig lastet og analysert, men før DOMContentLoaded-hendelsen til dokumentobjektet.

Dessverre fungerer ikke denne mekanismen for øyeblikket i alle nettlesere (spesielt IE). Fungerer heller ikke hvis det er document.write-linjer i script.js-filen.

Asynkron lasting javascript-skript fra Google

Som alle eksperter vet, legger Google spesielt vekt på lastehastigheten til nettsteder og senker de trege i søkeresultatene. For å hjelpe har Google utviklet et spesielt skript som du kan gjøre asynkron javascript-lasting med.

For å bruke, bare bytt ut


Og koble til skriptfilen extsrc.js

Det vil bli slik:

< script src= "http://extsrcjs.googlecode.com/svn/trunk/extsrc.js" > < script extsrc= "...." >

Denne metoden fungerer dessverre heller ikke for filer med document.write

Fungerer best asynkront laster javascript

En universell metode for alle nettlesere. Fungerer til og med med document.write

På stedet på siden der vi faktisk trenger å vise elementet vårt, lag en tom div-blokk:

< div id= "script_block" class = "script_block" >

Helt på slutten av siden, før vi setter inn et skript for asynkron lasting av filer:

< div id= "script_ad" class = "script_ad" style= "display:none;" >Her er alle filer eller skript som må lastes.< script type= "text/javascript" >// flytt den til det faktiske visningsposisjonsdokumentet. getElementById("script_block" ) . appendChild(dokument. getElementById("script_ad" ) ); // vis dokument. getElementById("script_ad" ) . stil. display = "blokk" ;

I de eldste versjonene av IE (6 og under) fungerer dessverre ikke asynkron lasting, men det er praktisk talt ingen slike brukere lenger. Alle andre nettlesere og tjenester bruker vellykket moderne akselerert lasting av nettsider.