Zepto Builder: van idee tot uitwerking

Door E-sites, E-sites
23 december 2013 - 3512 x bekeken - Categorie├źn: Tech

Zo nu en dan komt er een idee voorbij waar je als web developer iets mee moet doen. Degenen die zich aangesproken voelen weten ongetwijfeld waar ik het over heb, het voelt als een soort morele verplichting. Doorgaans zijn deze ideeën niet erg baanbrekend, maar soms zit er een kandidaat tussen die wel degelijk toegevoegde waarde kan hebben voor de developer community en waar je tegelijkertijd veel van kan leren. Het idee dat me onlangs te binnen schoot was wat mij betreft een typisch gevalletje “waarom bestaat dit nog niet?”.

Vandaar dat ik afgelopen week de tijd heb genomen om het idee in kwestie daadwerkelijk uit te werken. In deze blogpost ga ik jullie meer vertellen over de totstandkoming van het eindresultaat en welke tools ik daarvoor gebruikt heb.

Disclaimer: be on the uitkijk voor excessief gebruik van Engelstalig vakjargon.

Het idee

Naar aanleiding van een recentelijk gestart PhoneGap project was ik op zoek naar een compacte JavaScript library. Hoewel het aanbod hierin enorm is, dacht ik op basis van eerdere ervaringen vrijwel meteen aan Zepto.js, een library die qua syntax vergelijkbaar is met jQuery, maar een stuk minimalistischer is van opzet.

JavaScript libraries in het algemeen hebben de tendens om veel meer te omvatten dan het gemiddelde project vaak nodig heeft. Ook in dit geval had ik bij lange na niet alle functionaliteit nodig die Zepto te bieden heeft. Het ging me voornamelijk om de core logica. Na wat uitzoekwerk kwam ik erachter dat Zepto, vanwege zijn modulaire opzet, ook handmatig samen te stellen is via een command line interface (CLI) gebaseerd op Node.js. Hiermee kon ik precies aangeven welke modules ik nodig had. Ideaal.

Toen ik eenmaal een maatwerk versie klaar had staan was ik toch nieuwsgierig of er voor dit proces ook een online service beschikbaar zou zijn. Voor de grote, ietwat corpulente, broer van Zepto is hier namelijk ook al een handige tool voor. Na wat gerichte Google queries bleek dit, zover ik kon zien, niet zo te zijn. Vanaf dat moment was het idee voor Zepto Builder geboren.

De doelstelling

Over het gebruik van de command line als front-end developer zijn de meningen nogal verdeeld. Sommigen moeten er absoluut niets van hebben en werken het liefst met een grafische schil. Wat mij betreft zou een beetje front-ender de command line juist moeten omarmen. Als je kijkt naar het grote aantal handige npm packages en andere CLI tools doe je jezelf, als developer, te kort door er geen gebruik van te maken.

Aan de andere kant zijn er natuurlijk ook scenario’s te bedenken waarbij men, om wat voor reden dan ook, geen CLI tot zijn of haar beschikking heeft. In dat geval is het handig om een online web based equivalent te hebben. En dat is precies de doelstelling van Zepto Builder; het vergemakkelijken van een proces wat normaal gesproken op de command line plaatsvindt en dit beschikbaar maken voor een breder publiek.

Het opzetten van de interface

Na het uitdenken van het concept, was het tijd om aan de slag gaan. Als ik zeg dat bij een applicatie als deze een minimalistische interface een must is, dan is daar geen woord van gelogen. Dus, geen scroll hijacking, funky parallax effecten of dansende bananen Je selecteert de modules die je wil hebben, je drukt op een knop en klaar is je custom build. Niets meer, niets minder.

Nu zou ik natuurlijk zelf een interface kunnen ontwerpen, ware het niet dat ik een nogal beroerde designer ben. Sterker nog, ik ben helemaal geen designer. Period. Gelukkig zijn er vandaag de dag allerlei handige tools beschikbaar waardoor ik me hierover niet druk hoef te maken.

Tijdens de zoektocht viel mijn kritisch oog al snel op Adobe’s Topcoat. Met “CSS for clean and fast web apps” als slogan hadden ze mijn aandacht direct te pakken. Daarnaast heeft Topcoat een aantal mooie key features die mijn beslissing verre van lastig maakte, namelijk:

  • dito performance: alle onderdelen zijn gebenchmarked en maximaal geoptimaliseerd;

  • zeer gevarieerd: het biedt standaard een uitgebreide set met CSS componenten;

  • prima onderhoudbaar: Topcoat is gebaseerd op de BEM architectuur en daarmee minder contextueel en eenvoudig uit te breiden.

Kortom, een prima kandidaat voor de interface van Zepto Builder. Het duurde dan ook niet lang of ik had op basis van de bestaande componenten en wat maatwerk CSS een simpele interface op m’n beeldscherm staan.

 

JavaScript architectuur

Nu ik me over de interface geen zorgen meer hoefde te maken was het tijd om na te denken over de JavaScript architectuur. Omdat ik al vaker met dit bijltje heb gehakt wist ik via GitHub vrij snel een verzameling aan scripts bij elkaar te sprokkelen die me een hoop tijd zouden besparen. Ik ging aan de slag met de volgende setup:

  • Zepto: altijd handig om wat browserverschillen mee glad te strijken, en gezien de context moest deze library er natuurlijk gewoon inkomen. Uiteraard wel een custom build met alleen de modules die ik echt nodig had.

  • RequireJS: een welbekende en veelgebruikte JavaScript module loader waarmee ik alles netjes modulair op heb kunnen zetten.

  • Almond:  een minimale AMD API implementatie, ideaal in combinatie met de optimalisatie tool van RequireJS, hier later meer over.

  • DownloadBuilder: een JavaScript library die gebruik maakt van de HTML5 Filesystem API om meerdere bestanden samen te voegen tot één custom build. Het is voornamelijk dit script dat mij een hoop maatwerk logica heeft bespaard.

  • Base64.js: een polyfill voor browsers die geen support bieden voor window.btoa en window.atob (waar DownloadBuilder gebruik van maakt)

  • Uglify: dé oplossing als het gaat om het comprimeren van JavaScript code, uiteraard een must-have voor Zepto Builder.

RequireJS

Na het uitzoeken van de externe scripts heb ik een centraal RequireJS entrypoint opgezet welke als volgt aangeroepen wordt vanuit index.html:

<!-- build:js assets/js/build.min.js -->
<script src="assets/bower/requirejs/require.js" data-main="assets/js/main"></script>
<!-- /build -->

Hierbij gaat het voornamelijk om het data-attribuut met de verwijzing naar assets/js/main, het gebruik van de HTML comments kom ik later in de atikel op terug. In main.js wordt RequireJS geconfigureerd en wordt de core logica van Zepto Builder (asynchroon) ingeladen.

Core logica

Het hart van de applicatie is ZeptoBuilder.js en maakt zoals eerder aangegeven voornamelijk gebruik van de DownloadBuilder en UglifyJS.


De logica in dit bestand is, omwille van performance en maintainability, zoveel mogelijk opgesplitst in losse functies. Daarnaast worden DOM lookups beperkt en data gecached waar nodig. Het parsen van de lijst met modules, nadat deze is opgehaald van GitHub (of uit de cache), is gedaan met een simpele functie van drie regels, hier wordt dus geen hele template library (zoals Handlebars) voor ingeladen. Less is more.


 

Maintainability

Met in mijn achterhoofd het idee dat ik Zepto Builder zeer waarschijnlijk ook op GitHub ga plaatsen, heb ik de tijd genomen om de maintainability goed in kaart te brengen.

Wat we namelijk willen voorkomen is dat, elke keer wanneer meneer Fuchs zijn modules aanpast, we die betreffende veranderingen ook moeten doorvoeren in onze codebase. Vandaar dat ik gekozen heb om niet alleen de informatie van de beschikbare modules op te halen, maar ook de code van de modules zelf. Dit alles loopt via de GitHub API en wordt aangestuurd door JSONP logica.

Om onnodige API aanvragen te voorkomen worden de resultaten van de betreffende calls opgeslagen in de browser sessie via sessionStorage.

Package management

Het scenario wat ik hierboven schets voor wat betreft de maintainability geldt natuurlijk ook voor externe scripts die gebruikt worden in het project. Om dit te waarborgen maak ik gebruik van Bower, een package manager gebaseerd op Node.js en ontwikkeld door de devs van Twitter. De packages die je wil gebruiken kunnen opgegeven worden in een centraal bestand genaamd bower.json en opgehaald worden via de command line met het commando: bower install

Wanneer je twijfelt of jouw favoriete script te gebruiken is als bower package kun je deze opzoeken via de centrale registry.

Pro-tip: standaard worden de packages gedownload in de map ‘bower_components’ die in de root van je projectmap wordt geplaatst. Wanneer je, net als ik, niet houdt van een wildgroei aan mappen in de root kun je dit overschrijven door de gewenste map op te geven in het .bowerrc bestand.

Optimaliseren tot falen

Tijdens de ontwikkeling maak ik voor alle resources gebruik van de ongecomprimeerde versies, dit is met name handig als je bepaalde onderdelen moet debuggen. In een prodructie omgeving willen we natuurlijk alles maximaal optimaliseren en zo klein mogelijk houden. Om dit te realiseren heb ik gekozen voor Grunt.


Voor degenen die niet of nauwelijks bekend zijn met deze tool; Grunt (afgeleid van “grunt work”) is een JavaScript task runner welke werkt op basis van de command line en op Node.js draait. Het zal je dan ook niet verbazen dat Grunt plugins gebruik maken van npm en met een simpel commando (npm install pluginnaam) te installeren zijn.

Het voorbereiden van Grunt wordt op deze pagina haarfijn uitgelegd en is binnen no-time geregeld. Er zijn eigenlijk maar twee bestanden benodigd om het zaakje up & running te krijgen, namelijk:

  • package.json: hierin staat alle metadata van het project en kan aangegeven worden welke Grunt plugins vereist zijn;

  • Gruntfile.js: in dit bestand kunnen alle plugins geconfigureerd worden.

In het geval van Zepto Builder wordt Grunt gebruikt om automatisch een zogenaamde distributie build te maken die direct geschikt is voor een productie omgeving. Dit proces bevat de volgende stappen:

  1. Allereerst wordt de map waarin de uiteindelijke distributie bestanden moeten komen volledig opgeschoond.

  2. Daarna wordt gecontroleerd of de maatwerk JavaScript code voldoet aan de interne richtlijnen van E-sites.

  3. De CSS en JavaScript referenties in index.html worden gebundeld naar één HTTP request per onderdeel (dit gebeurt met de processhtml taak en op basis van de eerder genoemde HTML comments).

  4. Alle benodigde bestanden worden gekopieerd naar de distributie map.

  5. Het gekopieerde index.html bestand wordt volledig geminified en gestript van onnodige karakters en witruimte.

  6. Met de optimalisatie tool van RequireJS worden alle gebruikte JavaScript bestanden samengevoegd tot één bestand en wordt RequireJS zelf omgewisseld voor Almond, de lichtgewicht variant.

  7. Vervolgens wordt er met uncss, een Grunt task van Googler Addy Osmani, alle onnodige CSS weggegooid. Dit scheelt de nodige kilobytes aangezien er nogal wat Topcoat componenten zijn die we niet gebruiken.

  8. Tot slot wordt een automatisch gegenereerde banner geplaatst in het JavaScript bestand zodat de copyrights et cetera ook op orde zijn.

Zoals je ziet zijn er aardig wat taken die Grunt uitvoert om een complete distributie versie klaar te zetten. Desondanks gaat dit als de brandweer en hoef je nauwelijks te wachten.

Nadat dit gedaan is kan de distributie versie direct gepubliceerd worden naar een productie omgeving. Aangezien alle resources relatief worden aangeroepen zou de hele bundel ook in een submap geplaatst kunnen worden.

Open-sourcen op GitHub

Zoals eerder aangeven was ik eigenlijk vanaf het eerste moment al van plan om Zepto Builder uiteindelijk ook beschikbaar te stellen op GitHub. Op deze manier kunnen andere developers ook bijdragen aan de code en kan er toegewerkt worden naar een nog betere service.

Om dit proces in de goede banen te leiden hebben we intern een aantal richtlijnen waaraan we ons houden als projecten naar GitHub pushen. Hierin staan voor de hand liggende zaken zoals het plaatsen van de juiste license file en het verzorgen van Engelstalige documentatie. Al onze GitHub projecten worden verder ook gehost op een centraal subdomein.

In het geval van Zepto Builder heb ik een beknopte documentatie geschreven waarin ik uitleg hoe de tool onder water werkt en wat je moet doen om een distributie build te maken. Uiteraard mogen ook zaken als browser support, een roadmap, credits en licentie type vermelding niet ontbreken.

Verder is het goed om te vermelden dat de unit tests, die momenteel nog ontbreken, inmiddels gepland staan voor de volgende release.

Epiloog

Na het open-sourcen op GitHub kijk ik terug op een, weliswaar kort, maar geslaagd en leerzaam ontwikkelproces. Klinkt cliché, maar het is niet dat je elke dag bezig bent met API’s als de HTML5 FileSystem of de browser build van UglifyJS.

Alles bij elkaar opgeteld ben ik ongeveer een dag met Zepto Builder bezig geweest en is er in een relatief kort tijdsbestek een handige tool neergezet voor de front-end community.

En als je dan ook nog eens, kort na het bekend maken, een positieve reactie krijgt van Thomas Fuchs, (de maker van Zepto.js) dan geeft dat ondergetekende absoluut een voldaan gevoel.

 

 

Wij zoeken collega's!

Wil jij deel uitmaken van een bureau met een passie voor technologie? Kijk dan snel naar onze openstaande vacatures!

 

Op jacht naar de bugs!

Door E-sites

Waarom testen zo belangrijk is. - Lees meer

Lees verder