Eenvoudig script laden met yepnope.js

Officieel uitgegeven door Alex Sexton en Ralph Holzmann eind februari 2011, beschikt de yepnope.js-bronlader over asynchroon, voorwaardelijk laden en vooraf laden van zowel JavaScript- als CSS-bronnen. Dit maakt het beheren van afhankelijke, voorwaardelijke code een eitje.

Opnieuw gepubliceerde zelfstudie

Om de paar weken bekijken we enkele van onze favoriete lezers uit de geschiedenis van de site. Deze tutorial werd voor het eerst gepubliceerd in maart 2011.

Deze handige resource-loader, die slechts 1,6 KB verkleind en gzipped is, is nu gebundeld met Modernizer en is geweldig voor het laden van polyfills, het vooraf laden of "primen" van de gebruikerscache, of als een eenvoudige asynchrone resource loader / filter!

Voor degenen onder u die niet bekend zijn met polyfills, zijn het in essentie plug-ins of shims, die het gebruik van nieuwe of toekomstige technologieën in oudere browsers mogelijk maken, bijvoorbeeld web-sql-databases, CSS3-transformaties, enz.

Yepnope ondersteunt nu ook een aantal voorvoegsels en filters, die, wanneer ze worden toegevoegd aan de bron-url, nog een laag van fijne afstemming of aanpassing toevoegen aan de kernfunctionaliteit. Alsof dit nog niet geweldig was, biedt yepnope je ook een mechanisme om je eigen voorvoegsels en filters te definiëren. Laten we eens kijken naar wat yepnope.js kan doen!


Achtergrond - laden van asynchrone scripts

Voordat we ingaan op yepnope en de functies ervan, is het belangrijk om een ​​beetje te begrijpen hoe asynchroon laden van scripts werkt, waarom het nuttig is en hoe het verschilt van laden van vanilla-scripts.

Asynchrone laders verwijderen de inherente blokkering van een script.

Typisch JavaScript-bestanden geladen met de > tag, blokkeer de download van bronnen en de rendering van elementen binnen de webpagina. Dus hoewel de meeste moderne browsers geneigd zijn om de parallelle download van JavaScript-bestanden te ondersteunen, moeten beelddownloads en pagina-rendering nog steeds wachten tot de scripts klaar zijn met laden. Op zijn beurt neemt de tijd die een gebruiker moet hebben om te wachten tot de pagina wordt weergegeven toe.

Dit is waar asynchrone laders binnenkomen om te spelen. Met behulp van een van de verschillende verschillende laadtechnieken verwijderen ze de inherente blokkerende aard van een script, waarmee parallelle downloads van zowel de JavaScripts als bronnen kunnen worden uitgevoerd zonder de weergave van de pagina te hinderen. In veel gevallen kan dit de laadtijd van de pagina's soms drastisch verminderen.

De meeste loaders behouden de volgorde waarin scripts worden uitgevoerd en bieden een callback voor wanneer het script is geladen en gereed is.

Asynchroon laden komt echter niet zonder zijn beperkingen. Wanneer scripts op de traditionele manier worden geladen, wordt inline-code niet geparseerd of uitgevoerd totdat de externe scripts volledig zijn geladen, achter elkaar. Dit is niet het geval bij asynchrone belasting. Inline scripts zullen meestal worden geparseerd / uitgevoerd terwijl de scripts worden nog steeds gedownload. Op dezelfde manier downloadt de browser ook middelen en rendert de pagina terwijl de scripts worden geladen. We kunnen dus situaties bereiken waarin inline code, die misschien afhankelijk is van een script / bibliotheek die wordt geladen, wordt uitgevoerd voordat de afhankelijkheid ervan gereed is of voordat / nadat de DOM zelf gereed is. Als zodanig behouden de meeste loaders de volgorde waarin scripts worden uitgevoerd, terwijl ze een callback leveren voor wanneer het script is geladen en gereed is. Dit stelt ons in staat om elke afhankelijke inline-code als een callback uit te voeren, misschien binnen een DOM-ready-wrapper, indien van toepassing.

Ook, wanneer het gaat om een ​​kleine of goed geoptimaliseerde pagina, kan de DOM daadwerkelijk klaar zijn of zelfs worden geladen voordat de scripts zelf zijn geladen! Dus, als de betreffende pagina niet progressief wordt verbeterd, in die zin dat hij sterk afhankelijk is van JavaScript voor styling, kan er een FOUC of een flits van niet-gestileerde inhoud zijn. Op dezelfde manier kunnen gebruikers zelfs een korte FUBC of een flits van ongepaste inhoud ervaren. Het is belangrijk om deze dingen in gedachten te houden wanneer u een script / resource-loader gebruikt.


Stap 1 - De yepnope Test Object

De yepnope testobject heeft zeven basiseigenschappen, waarvan elk optioneel is. Dit object bevat de eigenlijke test, resources die als resultaat van de test worden geladen, resources die ongeacht de test en callbacks zullen worden geladen. Hier zijn de rekwisieten van het yepnope testobject:

  • test:

    Een booleaanse representatie van de toestand die we willen testen.

  • yep:

    Een tekenreeks of een array / object van tekenreeksen die de URL's van bronnen vertegenwoordigen die moeten worden geladen als de test is truthy.

  • Nee:

    Een tekenreeks of een array / object van tekenreeksen die de URL's van bronnen vertegenwoordigen die moeten worden geladen als de test is falsey.

  • laden:

    Een tekenreeks of een array / object van tekenreeksen die de URL's van bronnen vertegenwoordigen die moeten worden geladen, ongeacht het testresultaat.

  • beide:

    Een tekenreeks of een array / object van tekenreeksen die de URL's van bronnen vertegenwoordigen die moeten worden geladen, ongeacht het testresultaat. Dit is in principe syntactische suiker omdat de functie ervan over het algemeen hetzelfde is als de laden functie.

  • Bel terug:

    Een functie die wordt gevraagd elk bron omdat het opeenvolgend wordt geladen.

  • compleet:

    Een functie die wordt aangeroepen een keer wanneer alle bronnen zijn geladen.

Om nu een idee te krijgen van de syntaxis, laten we eens kijken naar het eenvoudigste gebruik van yepnope: het laden van één enkele bron.

 yepnope ( 'resources / someScript.js');

... of misschien een reeks bronnen laden.

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

Wat dacht je van een letterlijk object zodat we latere callbacks later kunnen gebruiken?

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

Onthoud dat deze bronnen asynchroon worden geladen wanneer de pagina wordt gedownload en weergegeven.


Stap 2 - Voorwaarden - Testen voor de functies van de toekomst!

We kunnen bronnen dus asynchroon laden! Dat is geweldig, maar wat als sommige pagina's geen bepaalde bron vereisen? Of, wat als een bron alleen nodig is in een bepaalde browser die geen geavanceerde nieuwe technologie ondersteunt?

Geen probleem! Dit is waar het onderliggende doel van yepnope in beeld komt. Met behulp van de testeigenschap kunnen we resources op basis van behoefte conditioneel laden. Laten we bijvoorbeeld aannemen dat de Modernizer-bibliotheek is geladen.

Voor degenen onder u die niet vertrouwd zijn met Modernizer, het is een handige test suite gebruikt voor het detecteren van HTML5 en CSS3 functie ondersteuning in browsers.

Modernizer voegt geschikte klassenamen aan de pagina's toe html element dat de ondersteunde en niet-ondersteunde functies vertegenwoordigt, b.v. "js flexbox no-canvas"enz. Bovendien hebt u toegang tot elk van de Modernizer-tests, die Booleaanse waarden afzonderlijk binnen uw code retourneren.

Dus, met behulp van Modernizer, laten we testen voor hashchange ondersteuning voor evenementen en ondersteuning voor sessiegeschiedenis!

Hier is een blik op onze test:

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

Deze test keert natuurlijk terug waar alleen als de browser beide functies ondersteunt.


Stap 3 - Resources laden voorwaardelijk

Als onze testconditie is ingesteld, definiëren we nu welke bronnen moeten worden geladen op basis van het resultaat van deze test. Met andere woorden, als u alleen een specifieke bron hoeft te laden wanneer de browser een functie mist, of als de test mislukt, kunt u eenvoudig die bron in de Nee clausule. Omgekeerd kunt u bronnen laden wanneer de test slaagt, binnen de ja clausule.

Dus, ervan uitgaande dat de browser geen van deze twee functies ondersteunt, laden we Ben Alman's jQuery hashchange-plug-in, die het mogelijk maakt hashchange en geschiedenisondersteuning in oudere browsers die geen van deze functies ondersteunen.

Laten we de hashchange-plug-in laden:

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

In het bovenstaande voorbeeld zullen we de ja eigendom, omdat we alleen een vulring leveren als dit nodig zou zijn.

Om het te illustreren ja clausule, laten we testen voor CSS3-transformatieondersteuning en vervolgens een stylesheet laden voor browsers die transformaties ondersteunen en een vanillestijlblad voor browsers die dat niet doen. Daarnaast laden we een jQuery-plug-in die ook CSS3-transformaties nabootst.

Zowel yep als nee gebruiken:

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

Merk op dat in beide voorbeelden alle bronnen asynchroon worden geladen terwijl de rest van de pagina wordt gedownload en gerenderd!


Stap 4 - Resources laden ongeacht de testvoorwaarde

Yepnope biedt ook een manier om bronnen onafhankelijk van de testresultaten te laden via de laden eigendom. De laden functie laadt altijd elke bron die het heeft ingevoerd, ongeacht de test resultaat. Evenzo is de beide prop, dat wil zeggen, nogmaals, in wezen gewoon syntactische suiker, laadt ook middelen ongeacht het testresultaat, of beter gezegd, op beide resultaten.

Standaard laden:

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

Laden op beide voorwaarden, syntactische suiker:

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

In beide bovenstaande voorbeelden worden bronnen asynchroon geladen, wat er ook gebeurt.


Stap 5 - Callbacks - Afhankelijke code na het laden

Zoals eerder vermeld, kunnen we geen in-line code op de gebruikelijke manier schrijven als die code afhankelijk is van een van de geladen scripts. Daarom gebruiken we de callback-functie van yepnope die eenmaal voor elke resource wordt geactiveerd na het is klaar met laden. De callback-functie accepteert drie parameters die aan het volgende zijn toegewezen:

  • url

    Deze tekenreeks vertegenwoordigt de URL van de resource die is geladen

  • resultaat

    Een boolean die de status van de belasting vertegenwoordigt.

  • sleutel

    Als u een array of een resource-object gebruikt, vertegenwoordigt dit de index of de eigenschapsnaam van het bestand dat is geladen

Laten we eens kijken naar een eenvoudige callback met het hashchange plugin-voorbeeld van eerder. We zullen de bindmethode van jQuery gebruiken om een ​​handler te binden aan de hashchange-gebeurtenis van de venster:

Een eenvoudige callback:

 yepnope (test: Modernizr.hashchange && Modernizr.history, nope: 'resources / jquery.ba-hashchange.js', callback: function (url, result, key) $ (function () $ (window) .bind ('hashchange', function () console.info (location.hash);););,);

Ongeacht de status waarin de DOM zich bevindt, wordt deze callback, die zich in dit geval binnen een voor het document geschikte wrapper bevindt, geactiveerd zodra de resource is geladen.

Laten we echter zeggen dat we meer dan één script laden en dat we voor elk script een callback moeten activeren wanneer het wordt geladen. Het opgeven van de code die we op de bovenstaande manier moeten uitvoeren, zou een redundantie creëren naarmate de callback wordt geactiveerd telkens wanneer een resource wordt geladen. Yepnope biedt echter een prima manier om callbacks voor elke resource af te handelen, onafhankelijk van andere callbacks.

Door een letterlijk object te gebruiken om de resources te definiëren die we laden, kunnen we elke resourcetoewijzing afzonderlijk raadplegen binnen de callback.

Laten we eens kijken naar een voorbeeld waarbij we jQuery laden, evenals de hashchange-plug-in jQuery, die afhankelijk is van het eerst laden van jQuery. Deze keer gebruiken we echter object-literals!

 yepnope (test: Modernizr.hashchange && Modernizr.history, nope: 'jquery': 'resources / jquery-1.5.1.min.js', 'hashch': 'resources / jquery.ba-hashchange.js' , callback: 'jQuery': functie (url, result, key) console.info ('Ik zal alleen vuren wanneer het jQuery-script is geladen');, 'hashch': functie (url, resultaat, sleutel)  console.info ('Ik zal alleen ontslaan als het hashchange-script is geladen'); // Deze code wordt toegevoegd aan de jQuerys DOM-gereed call-stack $ (function () $ (window) .bind ('hashchange', function ( ) console.info (location.hash););););

Als u het bovenstaande voorbeeld als referentie gebruikt, kunt u uw eigen callbacks voor elke resourcebelasting op een ordentelijke manier implementeren.


Stap 6 - Voltooien - Wanneer alles is gezegd en gedaan!

Ten slotte hebben we de compleet callback die slechts één keer wordt aangeroepen, nadat alle bronnen zijn geladen. Dus, bijvoorbeeld, als u een webtoepassing bootstraft en de code die u moet uitvoeren, afhankelijk is van alle bestanden die u laadt, in plaats van een Bel terug voor elke resource zou je je code binnen de compleet callback zodat het maar één keer wordt ontslagen, nadat alle afhankelijkheden zijn geladen. In tegenstelling tot de Bel terug functie, compleet neemt geen parameters of heeft toegang tot de url, resultaat of sleutel rekwisieten.

De compleet Bel terug:

 yepnope (test: Modernizr.hashchange && Modernizr.history, nope: ['resources / jquery-1.5.1.min.js', 'resources / jquery.ba-hashchange.js'], complet: function () console .info ('Ik zal slechts één keer starten wanneer zowel jQuery als het hashchange-script zijn geladen'); // Deze code zal worden toegevoegd aan jQuerys DOM ready call stack $ (function () $ (window) .bind ('hashchange' , function () console.info (location.hash););););

Dus, in wezen, de compleet terugbellen is handig voor alles wat moet worden gedaan zodra alle bronnen zijn geladen.


Stap 7 - Yepnope-plug-ins, voorvoegsels en meer!

Yepnope biedt ons ook nog een handige functie: voorvoegsels en filters! De standaard prefixen van yepnope, die altijd aan het begin van een resource-url zijn toegevoegd, worden gebruikt voor het definiëren van een bestand als CSS, het vooraf laden van een resource of het richten van respectievelijk Internet Explorer of een van de versies. Laten we eens kijken:

  • css!

    Dit voorvoegsel wordt gebruikt voor het forceren van yepnope om een ​​resource als een stylesheet te behandelen. Standaard behandelt yepnope .css-bestanden als stylesheets en al het andere als een JavaScript-bestand. Dus, als je CSS dynamisch opgeeft, dwingt dit voorvoegsel yepnope om die bron als een stylesheet te behandelen.

     yepnope ( 'css styles.php colorscheme = blauw!?');
  • preload!

    Met dit voorvoegsel kunt u een resource laden / cachen zonder deze uit te voeren.

     yepnope ( 'preload userInterface.js!');
  • d.w.z!

    Er kunnen zich omstandigheden voordoen waarin u alleen specifieke bronnen moet laden als u met Internet Explorer of een bepaalde versie van Internet Explorer werkt. Dus, de d.w.z voorvoegsels helpen u bij het laden van bronnen naar d.w.z of specifieke versies ervan. Hier is een lijst van de ondersteunde d.w.z voorvoegsels waar gt staat voor "versies groter dan" en lt staat voor "versies minder dan".

    • Internet Explorer:
      d.w.z!
    • Internet Explorer op versienummer:
      ie5!, ie6!, ie7!, ie8!, IE9!
    • Internet Explorer-versies groter dan:
      iegt5!, iegt6!, iegt7!, iegt8!
    • Internet Explorer-versies minder dan:
      ielt7!, ielt8!, ielt9!

    Al deze filters zijn koppelbaar en dienen als een soort van OF operator in dat als een van hen evalueert waar de resource wordt geladen. Dus, moeten we ons richten op ie7 en ie8, dan voegen we gewoon de juiste filters toe aan de url van de resource als volgt:

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

Eigen filters maken!

Mocht je ooit nodig hebben, yepnope biedt ook de middelen waarmee u uw eigen filters en voorvoegsels kunt maken via de addFilter en addPrefix methoden. Elk filter of prefix dat u maakt, wordt doorgegeven a resourceObject met een aantal nuttige rekwisieten. Vergeet echter niet om het resourceObject zoals yepnope vereist dat je dat doet. Hier is een blik op de resourceObject:

  • url:

    De URL van de bron die wordt geladen.

  • voorvoegsels

    De reeks toegepaste voorvoegsels.

  • autoCallback

    Een callback die wordt uitgevoerd nadat elk script is geladen, los van de andere scripts.

  • noexec

    Een Booleaanse waarde die voorspanning forceert zonder uitvoering.

  • in plaats daarvan

    Een geavanceerde functie die dezelfde parameters gebruikt als de lader.

  • forceJS

    Een boolean die de bron dwingt om te worden behandeld als javascript.

  • forceCSS

    Een booleaans die de resource dwingt om te worden behandeld als een stylesheet.

  • bypass

    Een boolean die bepaalt of de huidige resource al dan niet wordt geladen

Laten we bijvoorbeeld zeggen dat u de mogelijkheid wilt hebben om het laden van bronnen tussen uw CDN en de webserver onmiddellijk in te schakelen. Kunnen we dat toch doen? Yep! Laten we twee voorvoegsels maken, een voor het laden van de CDN en de andere voor het laden van uw webserver.

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

Met behulp van deze voorvoegsels kunnen we nu eenvoudig schakelen tussen onze CDN en de webserver!

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

Stap 8 - Een paar kanttekeningen

Dus, met behoud van een zeer kleine voetafdruk, is de voorwaardelijke lader van Yepnope boordevol met een aantal handige functies! Er zijn echter een aantal dingen waar u op moet letten voordat u het gebruikt.

  • Nee document.write

    Zoals met elke asynchrone lader, kunt u niet gebruiken document.write.

  • Internet Explorer minder dan 9 en callback-uitvoering

    Internet Explorer-versies van minder dan negen kunnen niet garanderen dat callbacks worden uitgevoerd per direct nadat het gerelateerde script is ontbrand.

  • Wees voorzichtig met de DOM

    Uw script kan worden geladen en uitgevoerd voordat de DOM gereed is. Dus, als je de DOM manipuleert, is het raadzaam om een ​​DOM-ready-wrapper te gebruiken.

  • Je moet nog steeds combineren waar je kunt

    Alleen omdat u een asynchrone lader gebruikt, betekent niet dat u uw bronnen niet zou moeten combineren waar mogelijk.

  • Asynchrone laadbeperkingen voor Internet Explorer

    Oudere versies van Internet Explorer kunnen alleen twee bronnen van hetzelfde domein tegelijkertijd laden, terwijl andere versies tot zes kunnen laden. Dus, als u meerdere bestanden laadt, overweeg dan om een ​​subdomein of CDN te gebruiken.


Conclusie - Gedachten over yepnope.js

Al met al vond ik yepnope een geweldig hulpmiddel! Het ondersteunt niet alleen het asynchroon laden van zowel scripts als stylesheets, maar het biedt u een mooie, schone manier om voorwaardelijke HTML5- en CSS3-polyfills te laden. Het callback-mechanisme is goed doordacht en de mogelijkheid om uw eigen voorvoegsels en filters toe te voegen is gewoon geweldig! Wat de prestaties betreft, vond ik dat yepnope enigszins op één lijn lag met andere loaders, zoals de LABj's van Getify Solutions en James Burke's require.js. Uiteraard is elke loader anders en past het in een andere behoefte, maar als je dit nog niet hebt gedaan, moedig ik je aan om yepnope.js te geven!