Easy Script Loading med yepnope.js

Offisielt utgitt av Alex Sexton og Ralph Holzmann i slutten av februar 2011, inneholder yepnope.js ressurslaster asynkron, betinget lasting og forhåndsbelastning av både JavaScript og CSS ressurser. Dette gjør styring avhengig, betinget kode en bris.

Publisert opplæring

Noen få uker besøker vi noen av leserens favorittinnlegg fra hele historien til nettstedet. Denne opplæringen ble først publisert i mars 2011.

Denne nifty ressurslasteren, som bare er 1.6KB-minifisert og gzipped, er nå kombinert med Modernizer og er perfekt for lasting av polyprofiler, forhåndsbelaste eller "priming" brukerens cache eller som en enkel asynkron ressurslaster / filter!

For de av dere som ikke er kjent med polypyfills, er de egentlig plugins eller shims som gjør det mulig å bruke nye eller fremtidige teknologier i eldre nettlesere, f.eks. web sql databaser, CSS3 transformasjoner osv.

Yepnope støtter nå også en rekke prefiks og filtre, som når det legges til ressursadressen, legger til et annet lag med finjustering eller tilpasning til kjernefunksjonaliteten. Som om dette ikke allerede var bra, gir yepnope deg også en mekanisme for å definere dine egne prefiks og filtre. La oss ta en titt på hva yepnope.js kan gjøre!


Bakgrunn - Loading Asynchronous Script

Før vi dykker inn i yepnope og dens funksjoner, er det viktig å forstå litt om hvordan asynkron skriptlasting virker, hvorfor det er nyttig og hvordan det er forskjellig fra vaniluscript-lasting.

Asynkronlastere fjerner den innebygde blokkeringsegenskapen til et skript.

Vanligvis JavaScript-filer lastet med > tag, blokkere nedlasting av ressurser, samt rendering av elementer på nettsiden. Så selv om de fleste moderne nettlesere pleier å støtte parallell nedlasting av JavaScript-filer, må bilder nedlastinger og sidegengivelse vente på at skriptene skal fullføres. I sin tur øker mengden tid en bruker må vente på siden som skal vises.

Det er her som asynkronlastere kommer inn for å spille. Ved å bruke en av flere forskjellige belastningsteknikker fjerner man den iboende blokkering av et skript, som muliggjør parallell nedlasting av både JavaScripts og ressurser mens det ikke forstyrrer sidegengivelse. I mange tilfeller kan dette redusere - noen ganger drastisk - siden lastetider.

De fleste lastere behold rekkefølgen der skript utføres mens de tilbakekaller for når skriptet er lastet og klar.

Asynkron lasting kommer ikke uten sine advarsler, skjønt. Når skript lastes på den tradisjonelle måten, blir ikke inline-koden parset eller utført til de eksterne skriptene er fullt lastet, i rekkefølge. Dette er ikke tilfelle med asynkron lasting. Faktisk vil inline-skript vanligvis analysere / utføre samtidig som Skriptene blir fortsatt lastet ned. På samme måte laster nettleseren også ressurser og gjengir siden når skriptene lastes inn. Dermed kan vi komme til situasjoner der inline-kode, som kanskje er avhengig av et skript / bibliotek som lastes, utføres før avhengigheten er klar eller før / etter at DOM selv er klar. Som sådan beholder de fleste lastere rekkefølgen der skript utføres mens de tilbakekaller for når skriptet er lastet og klar. Dette tillater oss å kjøre en hvilken som helst avhengig inlinekode som tilbakekalling, kanskje, innenfor en DOM ready wrapper, der det er aktuelt.

Også når det gjelder en liten eller godt optimalisert side, kan DOM faktisk være klar eller til og med lastet før skriptene selv er ferdig med å laste! Så hvis den aktuelle siden ikke blir gradvis forbedret, fordi den er avhengig av JavaScript for styling, kan det være en FOUC eller flash av ustilt innhold. På samme måte kan brukerne til og med oppleve en kort FUBC eller flash av uoppdragelig innhold. Det er viktig å holde disse tingene i bakhodet når du bruker et skript / ressurslaster.


Trinn 1 - The yepnope Test objekt

De yepnope testobjekt har syv grunnleggende egenskaper, hvorav noen er valgfrie. Dette objektet inneholder den faktiske testen, ressursene som vil bli lastet som et resultat av testen, ressurser som vil bli lastet, uavhengig av testen, samt tilbakekallinger. Her er en titt på yepnope-testobjektets rekvisitter:

  • test:

    En boolsk representerer tilstanden vi vil teste.

  • Jepp:

    En streng eller et array / objekt av strenger som representerer urlets ressurser for å laste om testen er truthy.

  • Nei:

    En streng eller et array / objekt av strenger som representerer urlets ressurser for å laste om testen er falsey.

  • laste:

    En streng eller et array / objekt av strenger som representerer urlets ressurser for å laste uavhengig av testresultatet.

  • både:

    En streng eller et array / objekt av strenger som representerer urlets ressurser for å laste uavhengig av testresultatet. Dette er i utgangspunktet syntaktisk sukker som sin funksjon er generelt den samme som laste funksjon.

  • Ring tilbake:

    En funksjon som vil bli kalt for Hver ressurs som den er lastet i rekkefølge.

  • fullstendig:

    En funksjon som vil bli kalt en gang når alle ressursene er lastet inn.

Nå, for å få en ide om syntaksen, la oss ta en titt på den enkleste mulige bruken av yepnope: lasting av en enkelt ressurs.

 yepnope (ressurser / someScript.js ');

... eller kanskje laster en rekke ressurser.

 yepnope (['resources / someScript.js', 'resources / someStyleSheet.css']);

Hva med et objekt bokstavelig, slik at vi senere kan bruke navngitte tilbakekallinger?

 yepnope ('someScript': 'resources / someScript.js', 'someStyleSheet': 'resources / someStyleSheet.css');

Husk at disse ressursene lastes asynkront ettersom siden lastes ned og gjengis.


Trinn 2 - Betingelser - Testing for fremtidens funksjoner!

Så, vi kan laste ressursene asynkront! Det er bra, men hva om noen sider ikke krever en viss ressurs? Eller, om en ressurs bare er nødvendig i en bestemt nettleser som ikke støtter en ny teknologi?

Ikke noe problem! Det er her yepnopes underliggende formål kommer i fokus. Ved hjelp av testegenskapen kan vi betinget laste ressurser basert på behov. For eksempel, anta at Modernizer-biblioteket er lastet.

For de som ikke er kjent med Modernizer, er det en nifty test suite som brukes til å oppdage HTML5 og CSS3-funksjonstøtte i nettlesere.

Modernizer legger til passende klassenavn på sidene html element som representerer funksjonene som støttes og ikke støttes, f.eks. "js flexbox no-canvas"etc. I tillegg kan du få tilgang til alle Modernizer-tester, som returnerer boolske verdier, individuelt, innenfor koden din.

Så, bruk Modernizer, la oss teste for hashchange hendelse støtte samt økt historie støtte!

Her er en titt på vår test:

 yepnope (test: Modernizr.shashchange && Modernizr.history);

Denne testen kommer selvfølgelig tilbake ekte bare hvis nettleseren støtter begge disse funksjonene.


Trinn 3 - Laster ressurser betinget

Med vår testbetingelse satt, definerer vi nå hvilke ressurser som skal lastes basert på resultatet av denne testen. Med andre ord, hvis du bare trenger å laste inn en bestemt ressurs når nettleseren mangler en funksjon, eller testen mislykkes, kan du enkelt definere den ressursen i Nei klausul. Omvendt kan du laste ressurser når testen passerer, innenfor Jepp klausul.

Så, forutsatt at nettleseren ikke støtter en av disse to funksjonene, laster vi opp Ben Almans jQuery hashchange plugin, noe som gjør det mulig hashchange og historisk støtte i eldre nettlesere som ikke støtter noen av disse funksjonene.

La oss laste opp hashchange-plugin:

 yepnope (test: Modernizr.shashchange && Modernizr.history, nope: 'resources / jquery.ba-hashchange.js');

I eksemplet ovenfor vil vi ikke bruke Jepp eiendom som vi bare gir en shim bør det være nødvendig.

For å illustrere Jepp klausul, men la oss teste for CSS3 transformasjonsstøtte og deretter laste et stilark for nettlesere som støtter transformasjoner og et vanilje stilark for nettlesere som ikke gjør det. I tillegg laster vi inn et jQuery-plugin som etterligner CSS3-transformasjoner.

Bruke både yep og nope:

 yepnope (test: Modernizr.csstransforms, yep: 'ressurser / cssTransform.css' nope: ['ressurser / noTransform.css', 'jQuery.pseudoTransforms.js']);

Merk at begge disse eksemplene vil laste alle ressurser asynkront som resten av siden laster ned og gjøres!


Trinn 4 - Laster ressurser uavhengig av testbetingelsen

Yepnope gir også en måte å laste ressurser på, uavhengig av testresultatene ved hjelp av laste eiendom. De laste funksjonen vil alltid laste inn hvilken som helst ressurs den er matet, uavhengig av test resultat. På samme måte, både prop, som igjen er hovedsakelig bare syntaktisk sukker, laster også ressurser uavhengig av testresultatet, eller mer nøyaktig, på begge resultatene.

Laster som standard:

 yepnope (test: Modernizr.shashchange && Modernizr.history, nope: 'resources / jquery.ba-hashchange.js', last: 'resources / somethingWhichIsAlwaysLoaded.css',);

Lasting på begge forhold, syntaktisk sukker:

 yepnope (test: Modernizr.shashchange && Modernizr.history, nope: 'resources / jquery.ba-hashchange.js', begge: 'Resources / somethingWhichIsAlwaysLoaded.css',);

I begge eksemplene ovenfor vil ressursene lastes, asynkront, uansett hva.


Trinn 5 - Tilbakeringinger - Avhengighetskode Etter belastning

Som nevnt tidligere kan vi ikke skrive in-line-kode på vanlig måte hvis den koden er avhengig av at et av skriptene lastes inn. Således bruker vi yepnopes tilbakeringingsfunksjon som branner en gang for hver ressurs etter den er ferdig lastet. Tilbakeringingsfunksjonen aksepterer tre parametere som er tildelt følgende:

  • url

    Denne strengen representerer URL-en for ressursen som ble lastet

  • resultat

    En boolsk som representerer lastens status.

  • nøkkel

    Hvis du bruker en matrise eller ressursobjekt, representerer dette indeksen eller egenskapsnavnet til filen som ble lastet

La oss ta en titt på en enkel tilbakeringing med hashchange-plugin-eksemplet fra tidligere. Vi bruker jQuery's bindemetode for å binde en handler til hashchange-hendelsen til vindu:

En enkel tilbakeringing:

 yepnope (test: Modernizr.shashchange && Modernizr.history, nope: 'ressurser / jquery.ba-hashchange.js', tilbakeringing: funksjon (url, resultat, nøkkel) $ (funksjon () $ ('hashchange', funksjon () console.info (location.hash);););,);

Uansett hvilken stat DOM er i, vil denne tilbakeringingen, som i dette tilfellet er innenfor et dokumentklar omslag, brenne så snart ressursen er lastet inn.

La oss imidlertid si at vi laster inn mer enn ett skript, og at vi må avfalle en tilbakeringing for hvert script som det laster. Angi koden vi trenger å kjøre på den ovenfor angitte måten, skaper en redundans da tilbakekallingen avfyres hver gang en ressurs er lastet. Yepnope gir imidlertid en flott måte å håndtere tilbakeringinger for hver ressurs, uavhengig av eventuelle tilbakekallinger.

Ved å bruke et objekt bokstavelig å definere ressursene vi laster inn, kan vi referere hver ressursnøkkel, individuelt, innen tilbakeringingen.

La oss se på et eksempel der vi laster jQuery, så vel som jQuery hashchange-plugin, som er avhengig av at jQuery lastes først. Denne gangen bruker vi objektobjektiver!

 yepnope (test: Modernizr.shashchange && Modernizr.history, nope: 'jquery': 'ressurser / jquery-1.5.1.min.js', 'hashch': 'ressurser / jquery.ba-hashchange.js' , callback: 'jquery': funksjon (url, resultat, nøkkel) console.info ('Jeg vil bare brenne når jquery-skriptet er lastet');, 'hashch': funksjon (url, resultat, nøkkel)  console.info ('Jeg vil bare brenne når hashchange-skriptet er lastet'); // Denne koden vil bli lagt til jQuerys DOM klar samtale stack $ (funksjon () $ (vindu). bind ('hashchange', funksjon ) console.info (location.hash););););

Ved hjelp av eksemplet ovenfor som referanse, kan du implementere dine egne tilbakeringinger for hver ressursbelastning på en ordnet måte.


Trinn 6 - Komplett - Når alt er sagt og gjort!

Til slutt har vi fullstendig tilbakeringing som bare kalles en gang, etter at alle ressursene er ferdig lastet. Så hvis du for eksempel "bootstrapping" et webprogram og koden du trenger å kjøre, er avhengig av alle filene du laster inn, i stedet for å spesifisere en Ring tilbake For hver ressurs vil du skrive koden din i fullstendig tilbakeringing slik at den bare fyres en gang, etter at alle avhengighetene er lastet. i motsetning til Ring tilbake funksjon, fullstendig tar ingen parametre eller har tilgang til url, resultat eller nøkkel Rekvisitter.

De fullstendig Ring tilbake:

 yepnope (test: Modernizr.hashchange && Modernizr.history, nope: ['ressurser / jquery-1.5.1.min.js', 'resources / jquery.ba-hashchange.js'], fullfør: funksjon () konsoll .info ('Jeg vil bare brenne en gang når både jquery og hashchange-skriptet er lastet'); // Denne koden vil bli lagt til jQuerys DOM ready call stack $ (funksjon () $ (vindu). bind ('hashchange' , funksjon () console.info (location.hash););););

Så, i hovedsak, fullstendig tilbakeringing er nyttig for alt som må gjøres når alle ressursene er lastet.


Trinn 7 - Yepnope-plugins, prefikser og mer!

Yepnope gir oss også en annen fin liten funksjon: prefiks og filtre! Standard prefikser levert av yepnope, som alltid er prepended til begynnelsen av en ressurs url, brukes til å definere en fil som CSS, henholdsvis forhåndsbelaste en ressurs eller målrette mot Internet Explorer eller en av dens versjoner. La oss se:

  • css!

    Dette prefikset brukes til å tvinge yepnope til å behandle en ressurs som et stilark. Som standard behandler yepnope .css-filer som stilark og alt annet som en JavaScript-fil. Så, hvis du serverer CSS dynamisk, vil dette prefikset tvinge deg til å behandle den ressursen som et stilark.

     yepnope ( 'css styles.php colorscheme = blå!?');
  • forspenning!

    Dette prefikset lar deg laste / cache en ressurs uten å utføre den.

     yepnope ( 'forbelaste userInterface.js!');
  • dvs!

    Det kan være omstendigheter hvor du bare trenger å laste inn bestemte ressurser hvis du arbeider med Internet Explorer eller en bestemt versjon av Internet Explorer. Dermed er dvs prefikser hjelper deg med å målrette ressursbelastning til dvs eller bestemte versjoner av det. Her er en liste over støttede dvs prefikser hvor gt står for "versjoner større enn" og lt står for "versjoner mindre enn".

    • Internet Explorer:
      dvs!
    • Internet Explorer med versjonsnummer:
      IE5!, IE6!, IE7!, IE8!, IE9!
    • Internet Explorer-versjoner større enn:
      iegt5!, iegt6!, iegt7!, iegt8!
    • Internet Explorer-versjoner mindre enn:
      ielt7!, ielt8!, ielt9!

    Alle disse filtrene er kjedbare og fungerer som en slags ELLER operatør i det hvis en av dem vurderer til ekte ressursen vil bli lastet inn. Så, bør vi må målrette ie7 og ie8, ville vi bare forordne de riktige filtre til ressursens URL som følger:

     yepnope ( '! ie7 IE8 userInterface.js!');

Opprette dine egne filtre!

Skulle du noen gang trenge det, yepnope gir også midler til å lage egne filtre og prefikser ved hjelp av addFilter og addPrefix metoder. Eventuelt filter eller prefiks du lager, er bestått a resourceObject inneholder et antall nyttige rekvisitter. Husk imidlertid å returnere resourceObject som yepnope krever at du gjør det. Her er en titt på resourceObject:

  • url:

    Url av ressursen lastet.

  • prefikser

    Utvalget av anvendte prefikser.

  • autoCallback

    En tilbakeringing som kjører etter hvert skript laster, skiller seg fra de andre.

  • noexec

    En boolsk verdi som styrker forhåndsbelastning uten kjøring.

  • i stedet

    En avansert funksjon som tar samme parametere som lasteren.

  • forceJS

    En boolsk som tvinger ressursen til å bli behandlet som javascript.

  • forceCSS

    En boolesk som tvinger ressursen som skal behandles som et stilark.

  • bypass

    En boolsk som bestemmer om den aktuelle ressursen skal lastes inn eller ikke

La oss for eksempel si at du vil ha muligheten til å bytte ressursbelastning mellom din CDN og webserver på fly. Kan vi gjøre det, skjønt !? Jepp! La oss lage to prefikser, en for lasting fra CDN og den andre for lasting fra webserveren din.

 yepnope.addPrefix ('local', funksjon (resourceObj) resourceObj.url = 'http: // mySite / resources /' + resourceObj.url; return resourceObj;); yepnope.addPrefix ('amazon', funksjon (resourceObj) resourceObj.url = 'http://pseudoRepository.s3.amazonaws.com/' + resourceObj.url; return resourceObj;);

Ved hjelp av disse prefiksene kan vi nå enkelt bytte mellom vår CDN og webserver!

 yepnope (['local! css / typography.css', 'amazon! defaultStyle.css']);

Trinn 8 - Noen advarsler

Så, mens du opprettholder et svært lite fotavtrykk, er yepnope betinget laster kraftig pakket med en rekke nyttige funksjoner! Det er imidlertid noen få ting du bør være oppmerksom på før du bruker den.

  • Nei document.write

    Som med hvilken som helst asynkron laster, kan du ikke bruke document.write.

  • Internet Explorer mindre enn 9 og tilbakeringing av tilbakekalling

    Internet Explorer-versjoner mindre enn ni garanterer ikke at tilbakeringinger kjøres umiddelbart etter det relaterte skriptet branner.

  • Vær forsiktig med DOM

    Skriptet ditt kan lastes og utføres før DOM er klar. Så, hvis du manipulerer DOM, er det tilrådelig å bruke en DOM ready wrapper.

  • Du bør fortsatt kombinere hvor du kan

    Bare fordi du bruker en asynkron laster, betyr det ikke at du ikke bør kombinere ressursene dine der du kan.

  • Asynkronlastgrenser for Internet Explorer

    Eldre versjoner av Internet Explorer kan kun laste to ressurser fra samme domene samtidig, der andre versjoner kan laste opp til seks. Så, hvis du laster inn flere filer, bør du vurdere å bruke et underdomene eller CDN.


Konklusjon - Tanker på yepnope.js

Alt i alt fant jeg yepnope å være et flott verktøy! Ikke bare støtter den asynkron lasting av både skript og stilark, men det gir deg en fin, ren måte å laste HTML5 og CSS3 polypyfills betinget. Tilbakekallingsmekanismen er godt gjennomtenkt, og muligheten til å legge til egne prefikser og filtre er bare bra! Ytelsesvis, jeg fant yepnope å være noe på nivå med andre lastere, som Getify Solutions 'LABjs og James Burke's require.js. Åpenbart er hver laster forskjellig og passer til et annet behov, men hvis du ikke har det ennå, oppfordrer jeg deg til å gi yepnope.js en tur!