Kaliber.js: één stack voor alles

T-shirt Erik: trust me I'm a programmer
Erik
Erik, Technical Director
Bij Kaliber ben ik samen met de andere developers altijd op zoek naar manieren waarop we beter en slimmer kunnen werken. Het viel mij op dat bij veel projecten de configuratie van de front-end stack afhing van de developer die er als eerste aan werkte. Hierdoor ontstonden er veel verschillende projectconfiguraties en kostte het updaten van de stacks meer tijd dan nodig. Om dit te optimaliseren, hebben we eind 2016 ons eigen pakket samengesteld: Kaliber.js. Nu zijn we in staat om onze updates op één plek uit te voeren.

Publicatie: 1 november 2019

De zoektocht naar Kaliber.js

De eerste vraag die we onszelf stelden was: welke set met tools gaan we gebruiken? Voor de build-tool passeerden verschillende opties de revue: Webpack, Gulp, Rollup, Parcel of zelf bouwen.

Na veel experimenten zijn we uiteindelijk uitgekomen bij Webpack. Deze tool sluit het beste aan bij onze wensen. Toch is ook Webpack niet ideaal; het configureren van Webpack is niet de makkelijkste taak. Een aantal uitdagingen:

  • Hot reloading. In Webpack is dit ongelooflijk lastig geïmplementeerd en dwong ons om tijdens development een speciale debug-server te gebruiken. Dit bleek onhandig wanneer we ook hot reloading wilden hebben bij WordPress sites. Uiteindelijk hebben we zelf een plugin voor Webpack gemaakt om hot reloading mogelijk te maken in al onze projecten.
  • CSS. De de facto standaard was een CSS loader in combinatie met een style loader en extract tekst plugin. Een complex systeem waar redelijk wat onhandigheden in zaten. We besloten om een eigen CSS loader te maken die vele malen simpeler was.
  • Source maps. Source maps zijn belangrijk tijdens development, maar zeker ook wanneer er bugs optreden als een site al in productie is genomen. De standaard oplossing van Webpack was wederom erg complex en functioneerde naar onze mening niet goed genoeg. Hiervoor hebben we wederom een eigen plugin ontwikkeld.
  • Chunks. Javascript en CSS worden vaak gedeeld door meerdere componenten op meerdere pagina’s. Om te zorgen dat een gebruiker niet meer hoeft te downloaden dan hij of zij nodig heeft, maken we pakketjes met de onderdelen die gedeeld worden tussen verschillende pagina’s. Hiervoor bestond de plugin common chunks die echter erg complex was om in te stellen. Ook hiervoor hebben we een eigen plugin geschreven. (Inmiddels heeft Webpack hiervoor zelf ook een mechanisme gemaakt die onze plugin heeft vervangen.)
  • React server-side rendering. Destijds was server-side rendering met React nog niet ‘common practice’. Next.js bestond al wel, maar was nog niet volwassen genoeg en voornamelijk gefocust op ‘build-time rendering’. Server-side rendering is van groot belang voor bots die zoekmachines en andere vormen van indexatie (denk aan delen op Facebook en LinkedIn) mogelijk maken. Tegenwoordig is het — met wat extra moeite — mogelijk om hier alternatieven voor te implementeren.

    Toch blijft server-side rendering nog steeds een goed idee omdat je de gebruikers sneller content kunt aanbieden. Dit heeft vervolgens weer een positieve impact op de page-score. Om dit zo laagdrempelig mogelijk te houden hebben we een Webpack plugin gemaakt die ‘universal’ rendering enorm simpel maakt.
hartje 3d

Richtlijnen voor Kaliber.js

Op technisch vlak hadden we een duidelijk plan, maar daarmee was het nog niet gedaan. Bij het maken van onze build-tool (een wrapper om Webpack) moesten we veel keuzes maken. Een aantal richtlijnen die we opstelden:

  1. ‘Zero configuration’. Het doel is om één dependency te downloaden en dan zonder configuratie meteen aan de slag te kunnen.
  2. ‘Convention over configuration’. Deze term is populair geworden door het framework Ruby on Rails en zegt dat we liever dingen afspreken dan dat we dingen configureerbaar maken. Een aantal praktische voorbeelden:
    - abc.entry.css: behandel dit bestand als een traditioneel css bestand. Classnames in dit bestand worden niet omgezet in hashes wat bij css modules wel gebeurt.
    - abc.html.js: deze bestanden worden opgepikt door de renderer die html produceert.
    - src/: alle bestanden leven in deze directory.
    - target/: hier worden de getransformeerde bestanden neergezet.

    Het sleutelwoord ‘opinionated’ is hier een belangrijk richtlijn. Door de conventies op te stellen zal deze tool mogelijk niet voor iedereen geschikt zijn. We hebben er voor gekozen om een tool te maken voor Kaliber.
  3. Open source. Bij een open source project heeft iedereen toegang tot je code. Het voordeel van een project open source maken is dat je er beter je best voor doet en dit komt de kwaliteit dan ook ten goede. Daarnaast kunnen mensen van buitenaf input geven en je zo inzichten geven in dingen waar je misschien nog niet over na had gedacht.
  4. Veranderingen. We moeten alle keuzes die we maken, verantwoorden. Hierover wijd ik hieronder verder uit.

Meegaan met ontwikkelingen

Om Kaliber.js up-to-date te houden, zijn er twee belangrijke vragen. Hoe zorgen we dat we geen belangrijke front-end development-trends missen? En hoe zorgen we dat we niet met élke hype meegaan?

Het ecosysteem van de front-end-wereld verandert snel en veel ontwikkelaars zijn snel geneigd om naar het nieuwste en hipste te springen. Hierdoor krijg je een enorme verscheidenheid aan onderdelen die het onderhoud weer moeilijk maken. En dat wilden we nu juist voorkomen.

Het evenwicht tussen deze vragen vinden we door alle keuzes te verantwoorden. Wanneer iemand iets wil veranderen, leggen we alle argumenten op tafel. Pas wanneer blijkt dat het argument vóór verandering zwaarder weegt, gaan we veranderen. Op het moment dat het niet uitmaakt of we links of rechts gaan — bijvoorbeeld wanneer het een kwestie van smaak is — houden we het zoals het is. Een transitie vraagt immers vaak om een behoorlijke investering. Een laatste vereiste voor verandering is dat we het direct kunnen toepassen. Een verandering moet gemotiveerd wordt door een écht project.

Resultaat: één stack voor alles

We gebruiken Kaliber.js inmiddels in alle projecten. Hierdoor hebben ontwikkelaars altijd dezelfde features in CSS en JavaScript tot hun beschikking.

Op dit moment — oktober 2019 — zitten we op versie 0.0.91. We hebben dus 91 iteraties gehad op Kaliber.js. We hebben 3 verschillende versies van Webpack gezien en 99 bugs en verbeteringen doorgevoerd.

Een kijkje in de keuken

Mocht je geïnteresseerd zijn in de code en hoe die er momenteel uit ziet, ga dan naar onze Github pagina. Wil je het daadwerkelijk gebruiken, in meer details lezen welke keuzes we hebben gemaakt, of kijken hoe je bepaalde dingen doet, check dan de documentatie.


Kaliber.js in de toekomst, what’s next?

In de toekomst zullen we waarschijnlijk een overstap maken naar Next.js. Zeit, de makers van Next.js, hebben een mooi product ontwikkeld en enorme stappen gezet. We delen veel dezelfde principes. Daarnaast hebben zij gekozen voor universal rendering. Dit is voor de toekomst een betere keuze dan de oplossingsrichting waar wij destijds voor kozen.

Om een overstap te kunnen maken zullen we echter eerst de oudere build stacks die nog in gebruik zijn de stap naar @kaliber/build moeten maken. Ons doel is om nooit meer dan twee verschillende vormen van hetzelfde te hebben. Dit zorgt ervoor dat applicaties goed te onderhouden blijven en dat de kennis van de tools onder developers gegarandeerd blijft.

Wanneer we een overstap maken naar een nieuwe build stack, blijft ons belangrijkste principe wel van kracht: maak één pakket dat de keuzes van Kaliber vastlegt. Zo behouden we die goede basis die we ook met Kaliber.js gecreëerd hebben.