Fotoimpressie
Fotoimpressie
Kennisdeling

Blog: Duurzame frontends bouw je met Web Components

  • 18 november 2022
  • 18-11-22
  • Geschreven door Wessel Loth
  • Wessel Loth
  • 6 minuten leestijd
  • 6 min

Frontends bouwen met frameworks staat voor mij gelijk aan nieuwe legacy code kloppen. Dat is mijn mening na het gebruiken van web components in de afgelopen paar jaren. Want wanneer je een stapje terug neemt kom je er achter dat alle frameworks hetzelfde proberen op te lossen: herbruikbare componenten maken, efficiënt HTML maken en manipuleren, encapsulation mogelijk maken en dit allemaal op een performant manier doen met een (Virtual) DOM engine. Oké, de ene developer vindt Hooks fijner werken dan iets met Classes. Of vindt de simpliciteit van Vue beter dan de Enterprise-ready aanpak van Angular. Maar aan het eind van de dag dienen ze hetzelfde doel: op een makkelijke manier gebruiksvriendelijke en interactieve webpagina’s maken voor onze eindgebruikers. Juist daarom pleit ik voor web components: een out-of-the-box manier om dit in je browser te bereiken, met nul afhankelijkheden van grote bedrijven om je framework te onderhouden.

Web Components 101
Veel bekende bedrijven als Google, Adobe, ING, Rabobank en de Politie zijn in de laatste jaren web components gaan gebruiken. Online hoor jij de term ook vast steeds vaker langskomen. Maar wat zijn ze nou eigenlijk?

 De use case voor web components zijn eigenlijk vrij makkelijk uit te leggen. Stel je voor: je wilt een dialog bouwen met het <dialog> element, maar wilt er nog wat maatwerk code aan toevoegen om het element aan te laten sluiten aan jouw wensen. Veel frontend developers denken dan meteen aan de mogelijkheden om dit met hun framework naar keuze te maken. Of hoe ze het in vanilla JavaScript zouden maken, wat voor veel nog steeds gelijk staat aan jQuery.

 Maar wat als je je eigen <fancy-dialog> element kon maken als overerving van het ingebouwde element? Met alle lifecycle hooks zoals je gewend bent van frameworks? En wat als dit component native in je browser kon draaien zonder NPM dependencies of build tooling? Dat is waar web components shinen.

 De term “web components” is eigenlijk een verzamenterm voor een groepje browserstandaarden. Met deze standaarden kan je maatwerk elementen op de pagina zetten die leven naast de ingebouwde elementen die je al kent. Dit wordt gedaan met drie standaarden: Custom Elements, Shadow DOM en HTML Templates. Elk van deze standaarden zijn een deel van de puzzel die web components heet.

Custom elements
Het fundament van web components. Namelijk de components zelf. Zoals de naam impliceert kan je hiermee je eigen elementen maken met een eigen HTML-tag zoals <fancy-dialog>. De enige vereisten: een element moet een klasse zijn die overerft van HTMLElement, en het moet een naam hebben met twee of meer woorden er in. Dit zodat de browser het onderscheid kan maken tussen de ingebouwde en custom elementen. Een simpel custom element kan er zo uit zien:

 

class FancyDialog extends HTMLElement {

  constructor() {

    super();

    this.innerHTML = `<some html to render>`;

  }

  // Other implementation details like handling events

}

customElements.define(‘fancy-dialog’, FancyDialog);

 

Nadat dit script is uitgevoerd op de pagina is het gebruik zo simpel als een <fancy-dialog> tag ergens op de pagina zetten. De laatste regel code is hier de belangrijkste: hier vertel je aan de custom element registry dat de FancyDialog klasse moet worden opgestart op het moment dat de bijbehorende tag wordt gevonden op de pagina. Na die stappen werkt het element zoals elke andere op de pagina: het is een node in de DOM-tree, events bubbelen zoals je gewend bent en je kan ze makkelijk stylen of manipuleren met selectors. Plus: nog twee bonussen. Deze componenten werken samen met componenten in elk ander framework, en alles werkt native in de browser zonder ook maar een enkele byte aan code in je node_modules directory.

Shadow DOM
Custom elements zijn op zichzelf al gaaf, maar mist nog een key feature: encapsulation. Encapsulation gaat over het verbergen van implementatiedetails aan de consument, en om te zorgen dat de innerlijke werking van een component geen invloed heeft op de werking van de rest van de webpagina. Dat is waar je Shadow DOM om de hoek komt kijken. Het concept hiervan is het beste te illustreren met het volgende diagram:

Elke node in de DOM kan je upgraden naar een shadow host. Vanaf dat punt kan je interacteren met deze nieuwe shadow root en er net als elke andere node ook children aan toevoegen met de querySelector en appendChild. Alle nodes in deze boomstructuur worden door de browser platgeslagen tot een enkele DOM structuur, met als verschil dat alles binnen de shadow tree niet wordt beïnvloed van buitenaf, en andersom. Dit maakt dat je in de shadow tree hele simpele CSS kan schrijven, zoals h1 { color: red; }. Deze styling regel geldt dan alleen binnen de shadow DOM en kan nooit naar buiten lekken. Events bubbelen zoals je gewend bent, met de bonus dat je zelfs op events kan configureren of ze wel of niet de shadow DOM-grenzen mogen passeren. Ook werkt de accessibility tree zoals je gewend bent: de nodes in de shadow DOM worden gewoon gezien als elke andere node op de pagina, en ondersteunende technologieën als schermlezers kunnen deze goed uitlezen.

 Het mooiste van de shadow DOM is dit: je gebruikt het al. Zelfs al weet je het nog niet. Want wanneer je enable user agent Shadow DOM in je developer tools instellingen aanvinkt kan je de implementatiedetails van ingebouwde browserelementen inspecteren. Zo kan je hier zien hoe de range-input implementatie er onder de motorkap uit ziet:

 

Zo zie je maar dat je met de shadow DOM echte encapsulation kan gebruiken op de webpagina zonder rare workarounds die de (Virtual) DOM-engines van frameworks gebruiken om hetzelfde doel te bereiken.

HTML Templates
Het laatste deel van de puzzel is een techniek om makkelijk HTML herbruikbaar te maken en updaten op de webpagina. Gelukkig hebben de browser vendors daar ook aan gedacht: HTML Templates. Het gebruik hiervan is simpel: maak een <template> element op de pagina, en zet er HTML & CSS in. Wanneer de browser dit template element tegenkomt in de DOM gebeurt er niet zo veel: de inhoud wordt geparsed en gevalideerd, maar de gebruiker krijgt niks te zien en media-URLs worden niet ingeladen. Pas op het moment dat je het nodig hebt kan je met een stukje JavaScript een supersnelle kloon maken van de template en ergens in de pagina zetten. Omdat de browser hier een low-level implementatie voor heeft met slimme caching is dit ook nog extreem snel.

Samen vormen deze drie standaarden dus “web components”. Wanneer je ze combineert heb je een wereldklasse systeem om componenten te bouwen. Een herkenbare syntax voor de elementen, een ingebakken manier voor encapsulation en een efficiënte manier om HTML te renderen. En de browser support? Die is top: alle greenfield browsers ondersteunen web components. En voor legacy browsers zijn er meer dan genoeg polyfills beschikbaar.

Libraries & Ecosysteem
Wanneer je kijkt naar web components vanuit het perspectief van een bedrijf komen er wat extra vragen bij kijken. Het gaat niet alleen om of de techniek werkt: er zijn ook wensen over de community, het ecosysteem en het toekomstperspectief. Kan je eigenlijk wel ontwikkelaars vinden die er ervaring mee hebben? En hoe soepel is de Developer Experience vergeleken met de grote frameworks?

Toen ik er eerst mee werkte voelde het zelfs magisch: net als vroeger een index.html maken, een script tag toevoegen met de custom element er in en bam! Het werkt zonder verassingen. Je kan met deze pure standaarden hierboven prima interactieve webapplicaties bouwen. Maar de standaarden geven niet alles wat frameworks je bieden: routing, bundling, building en nog veel meer. Om het een klein stukje makkelijker te maken zijn er libraries die uitbreiden op de standaarden en nét dat stapje extra bieden voor een modernere Developer Experience. De meest bekende libraries zijn:

  • Lit
  • Stencil
  • Angular Elements

Elk van deze libraries heeft sterke en zwakke kanten. De filosofie van Lit is om zo dicht mogelijk bij de browserstandaarden te blijven. Maar Stencil en Angular Elements laten dit helemaal los en richten zich op een batteries-included aanpak met structuren klaar voor de enterprise. Maar ongeacht de library is het mooiste dat aan het einde van de dag elk component overerft van HTMLElement en daarmee een native web component is. Mijn persoonlijke aanpak is om te beginnen met vanilla, te upgraden naar Lit wanneer nodig en pas verder te kijken wanneer je daar ook tegen limitaties aan loopt. Mijn reden hiervoor is dat de source code van Lit erg makkelijk is om te begrijpen, er geen build tooling nodig is om het werkend te krijgen en je geen enkele afhankelijkheid binnentrekt behalve Lit zelf.

Buiten de libraries om zijn er ook steeds meer ontwikkelingen in het ecosysteem. Open Web Components heeft gedetailleerde documentatie beschikbaar voor veelvoorkomende vragen, tooling en set-ups. Rocket biedt een zero-JS server side rendered toolchain vergelijkbaar aan Astro. Vaadin heeft een grote stapel enterprise componenten zoals grids beschikbaar voor gebruik. En de ING Bank heeft al hun basiselementen open source beschikbaar gemaakt, whitelabel zodat je makkelijk op een flexibele en toegankelijke manier jouw eigen design system kan opzetten. Deze voorbeelden zijn pas het puntje van de ijsberg: er zijn tegenwoordig ook veel actieve communities op Twitter en Slack die continu gave nieuwe ontwikkelingen delen.

Wanneer (niet) te gebruiken
Als je kijkt naar het bredere ecosysteem rondom web components dan zal je zien dat het steeds meer mainstream wordt en er ook hele bekenden bedrijven hun frontend applicaties zijn gaan bouwen met web components. Zelfs Photoshop draait tegenwoordig in de browser op web components: een technisch wonder ongeacht welke techniek ze hadden gekozen. Maar natuurlijk zijn er ook nadelen aan het switchen naar web components. Zo zal je wat langer moeten zoeken naar third-party componenten die exact bij jouw scenario past omdat er niet zo veel beschikbaar is op NPM als voor de grote frameworks. Of dat het best lastig kan zijn om goede resources te vinden online over de best practices. En een frontend developer vinden die al ruime ervaring heeft met web components? Veel succes, dat is een echte zoektocht naar een unicorn.

 Tóch denk ik dat het de tijd waard is voor iedere frontend developer of architect om zich in web components te verdiepen. Want tegenwoordig is het enorm makkelijk geworden om complexe frontend applicaties te bouwen op pure browser standaarden. Voor veel bedrijven is het al heel normaal geworden om frontends uit te rollen met (bijna) nul afhankelijkheden. Dus: tijd om je mouwen op te stropen en aan de slag te gaan! Want als je kiest voor web components, dan kies je voor een duurzame frontend die nog vele jaren op stabiele browser standaarden zal draaien.

 Meer lezen over web components? Check dan de uitgebreide blogpostserie van Wessel. Voor het eerst verschenen in de eerste editie van Frontmania Magazine in September 2022.

 


Deel deze update

Nieuws

Seven Stars voor de zevende keer op rij FD Gazelle

YES! Our lucky number Seven! Voor de 7 e keer op rij zijn we uitgeroepen tot één van de snelst groeiende ondernemingen van Nederland. We zijn...

lees meer
Nieuws

New 'STAR'giair: Sarina

Een nieuwe ‘STAR’giair! Sarina is gestart met haar stage bij Team Marketing & Communicatie. Ze volgt de opleiding Creative Business aan NHL Stenden...

lees meer
Nieuws

New Star: Meet Sabine

Nog een New Star? Ja, je ziet het goed! Meet onze nieuwste aanwinst: Sabine! Een veelzijdige vrouw die bij team belastingdienst gaat sparken als IT...

lees meer