Drupal als headless CMS: hoe benut je de voordelen?

De toepassing van een ‘headless’ of ‘decoupled’ CMS is aan een flinke opmars bezig. Met de ontwikkelingen in frontend frameworks als React, VueJS en Angular, en de groeiende behoefte aan het kunnen delen van content op verschillende platformen is de scheiding van inhoud en presentatie dan ook een logische stap. Als Drupal specialist zochten we een invulling die voortborduurt op onze huidige oplossingen. In dit artikel delen we onze bevindingen en presenteren we een opzet die wellicht voor jou ook kan werken.

 

4 december 2019
placeholder

Een headless CMS, wanneer wel en wanneer niet?

Als merkbeleving en gebruikerservaring prioriteit hebben op je website dan geeft een headless CMS veel meer flexibiliteit. De stap naar een webapplicatie is bovendien stukken eenvoudiger geworden en daarmee toekomstbestendiger.

Voor grote projecten die leunen op veel functionaliteit (die door Drupal wordt aangeboden) is een headless CMS echter vaak praktisch en financieel niet haalbaar: alle functionaliteit moet dan opnieuw geïmplementeerd worden. Daarbij is Drupal geoptimaliseerd voor onder andere SEO en de snelheid van laden. In de headless opzet staat dat echter nog in de kinderschoenen. Voor sites waar snelheid en vindbaarheid voorop staan is Drupal daarom voorlopig nog de betere keuze.

Dat neemt niet weg dat we de potentie van een headless CMS opzet veelbelovend vinden en verwachten we deze ook steeds vaker te gaan toepassen. De komende tijd gaan we dan ook investeren in de stapsgewijze migratie van functionele onderdelen om de toepasbaarheid te vergroten.

Bestaande oplossingen

Er zijn veel oplossingen voor headless websites: zowel SaaS-oplossingen (b.v. Contentful en Netlify) als open source software (b.v. Strapi). Ook bekende systemen als Drupal, Wordpress en Sitecore hebben oplossingen voor headless websites. Voor ons is een SaaS-oplossing meestal niet wenselijk; door de beperkingen van deze systemen zijn we veel minder flexibel en zitten we vast aan doorlopende contracten. Onze voorkeur daarom gaat uit naar self-hosted en open source.

Een andere categorie is static generators: systemen die een statische versie van de website genereren met dynamische content die te beheren is vanuit een CMS of vanuit code. Groot voordeel is dat de opzet eenvoudig is en de website supersnel omdat het allemaal statische data is. Sites met volledig statische data bieden echter vrijwel geen functionaliteit: je zult het dus zelf moeten ontwikkelen. Wij zijn echter op zoek naar een opzet waar we ook onderdelen als zoeken, formulieren en comments kunnen toevoegen.

Onze oplossing

Drupal als CMS

Drupal is een van de bekendere en grotere open source content management systemen en is geoptimaliseerd voor zowel eenvoudige als complexe content-structuren. Het biedt out-of-the-box oplossingen voor de meeste vraagstukken en kan naar wens worden uitgebreid met de vele modules die ontwikkeld en ondersteund worden door de community van ontwikkelaars.

Het lag voor de hand om op zoek te gaan wat de rol van Drupal is (en kan zijn) in een headless omgeving. Hoewel de nieuwe technieken in Drupal 8, waaronder de krachtige Twig template engine, nieuwe mogelijkheden bieden, blijft deze opzet wat 'oud' aanvoelen. Op het gebied van frontend zijn inmiddels grote stappen gezet; nu wordt het tijd om te kijken naar de vervolgstappen.

Al ruim 10 jaar gebruiken wij Drupal voor content-gedreven projecten. Sinds Drupal 8 is de kern van het systeem langzaam aan het verschuiven naar een API-first opzet: alle content die wordt gemaakt in Drupal is direct beschikbaar middels een API. Dat maakt het heel geschikt voor systemen waar de scheiding van presentatie en inhoud wenselijk zijn.

React als frontend

Voor vrijwel alle mobiele webapplicaties, en in sommige gevallen ook React Native voor native mobiele apps, gebruiken wij al heel lang React. Het is op dit moment dan ook met afstand het meest gebruikte front-end framework. React is 'component-based' wat wil zeggen dat elementen voor een website of app fungeren als bouwelementen die los van elkaar kunnen functioneren. Met het terugbrengen van onderlinge afhankelijkheden wordt de complexiteit kleiner en onderdelen beter herbruikbaar. Daarmee was het een logische keuze om de voorkant volledig in React op te zetten.

React, Redux en Immutable

Voor een duidelijke scheiding tussen vorm en inhoud kiezen wij voor de state manager Redux. Deze state bevat alle informatie die bepaalt wat de app op ieder gegeven moment toont. Om de scheiding te bewerkstelligen mag een state niet direct aanpasbaar zijn. In Redux moet dit middels het uitvoeren van actions, die worden opgepikt door reducers die de de state aanpassen waarbij de store verantwoordelijk is voor het vasthouden van de state. Om er zeker van te zijn dat de state niet direct aanpasbaar is, gebruiken we Immutable; een library die de data in de state niet-aanpasbaar maakt.

Rest API, JSON:API en GraphQL

Een decoupled opzet heeft naast een frontend en backend ook een communicatielaag nodig: de API. Drupal 8 komt standaard met een Rest API module die alle content beschikbaar stelt. Deze API is duidelijk en voldoet in principe volledig aan onze wensen. De data is echter nogal groot en log en is volledig gescheiden. Dit zorgt ervoor dat een grote hoeveelheid data moeten inladen en we overal losse calls voor moeten doen. Neem bijvoorbeeld een pagina waar twee referenties staan: één taxonomy term en één afbeelding. Dit zorgt er voor dat we drie losse calls moeten doen: één voor de pagina, vervolgens één voor de taxonomy term en één voor het bestand.

De JSON:API standaard is in het leven geroepen om tekortkomingen in standard Rest specificaties (of het gebrek daar aan) op te lossen. Zo heeft JSON:API een gespecificeerd formaat: er is een schema die de data beschrijft, een plek voor metadata, links naar gerelateerde resources, beschreven error meldingen, etcetera. Het heeft ondersteuning voor het bepalen welke data de server teruggeeft waardoor er minder data verstuurd hoeft te worden. Bovendien is het mogelijk om meerdere entiteiten in één keer op te halen waardoor de prestaties van de app aanzienlijk beter worden.

Daarnaast is er GraphQL, een query-taal ontwikkeld door Facebook die bovenstaande tekortkomingen oplost door meer verantwoordelijkheid te plaatsen aan de kant waar de data opgehaald wordt. In plaats van vaste endpoints zoals Rest en JSON:API dat hebben, heeft GraphQL in principe één endpoint waar de frontend verzoeken aan kan doen. De verzoeker kan bepalen welke data opgehaald wordt middels een query-taal. Daarbij kan gefilterd worden op velden en kunnen relaties tussen entiteiten opgehaald worden. De manier waarop deze verzoeken gedaan worden (het schema) is duidelijk beschreven en gedocumenteerd maar kan dusdanig complex worden dat het gebruik van wrapper libraries eigenlijk een must is. 

Dries Buytaert heeft een uitgebreid artikel geschreven over de vergelijking tussen deze technieken.

Onze keuze is vooralsnog op Rest gevallen. Dit met name omdat het out-of-the-box werkt met Drupal, aanzienlijk minder complex is om mee te beginnen, standaard caching ondersteunt en eenvoudig te implementeren is in de frontend. Het scheiden van data en presentatie door onze opzet met Redux en React maakt het schrijven bovendien makkelijker. Daarnaast gaan we door met het vinden van alternatieve oplossingen, met name om de snelheid verder te vergroten.

Decoupled Router

Eén van onze wensen was om de gebruikers meer een app-ervaring te bieden waarbij een klik naar een vervolgpagina geen pagina ververst. React is onder andere geschikt voor Single Page Applications (SPA). Oorspronkelijk was dit bedoeld voor webapplicatie-toepassingen maar zorgt ook bij puur informatieve websites een prettige gebruikerservaring.

Dit zorgt er voor dat het bepalen welke pagina aan de gebruiker moet worden getoond (de zogenaamde routing) nu in plaats van een taak van de backend een taak van de frontend wordt. Omdat content managers echter nieuwe pagina’s aan kunnen maken in het CMS, weet de webapp niet van het bestaan van deze pagina’s af. Telkens een nieuwe deploy wanneer een content manager een nieuwe pagina aanmaakt, is uiteraard geen oplossing.

Gelukkig bestaat er een Drupal module genaamd Decoupled Router. Deze module geeft een endpoint waar een URL-pad in kan en een pagina uit komt. Zodra de gebruiker een pagina opvraagt kan React zodoende een verzoek doen aan deze endpoint. Uit de response van de endpoint kan de app bepalen om welke pagina het gaat en hoe deze weer te geven.

Voor- en nadelen

Als gezegd, onze oplossing is niet voor elk project. Om je te helpen bepalen of onze oplossing geschikt is voor jouw project, sommen we hier de voor- en nadelen op.

Voordelen

  1. Meer opties, meer vrijheid en meer snelheid in ontwikkeling
    Zoals gezegd is Drupal een enorm krachtig CMS en vrijwel onvervangbaar in onze oplossing. Ook op het gebied van frontend zijn er in Drupal 8 grote stappen gezet. De recente ontwikkelingen in frontend development bieden inmiddels veel meer mogelijkheden en vrijheid. De combinatie met een snellere manier van ontwikkelen, hoeven we niet langer alles met Drupal op te lossen. Onze oplossing stelt je daarmee in de gelegenheid om sterke onderdelen te blijven gebruiken maar minder sterke juist te vervangen.  

  2. Meer flexibiliteit door het scheiden van systemen
    Het scheiden van systemen (decomposition) is een bekende strategie bij software-ontwikkeling. In plaats van één groot monolithisch geheel wordt het een systeem van los functionerende onderdelen die met elkaar communiceren. Dat is exact de opzet van een headless systeem en geeft een flexibele opzet: de presentatie staat los van de data en beide systemen kunnen los van elkaar functioneren, zelfs vervangen worden als het nodig is.  


  3. Beter gebruik van specifieke kennis van ontwikkelaars
    Ondanks dat onze manier van werken mensen stimuleert breed inzetbaar te zijn (T-shaped), is er een logische scheiding tussen de ontwikkelaars die zich met name focussen op data, structuur en logica (backend ontwikkelaars) en ontwikkelaars die zich met name focussen op presentatie en gebruikerservaring (frontend ontwikkelaars). Met het scheiden van deze twee lagen kunnen ontwikkelaars zich meer focussen op het gebied waar ze zich thuis voelen en hoeven zich niet bezig te houden met ontwikkelingen aan het andere systeem.  


  4. Beter hergebruik van componenten
    In Drupal gebruiken wij Features om onderdelen tussen verschillende sites te delen. Dit werkt goed voor puur functionele onderdelen maar niet zozeer voor de presentatie-laag omdat dit in Drupal niet strikt gescheiden is en daarmee verweven zit in de Features. Dit is met de komst van Twig aanzienlijk verbeterd, met name door de mogelijkheid om templates te ‘extenden’. Gebruik je echter CSS dan blijft het een kwestie van stapelen middels overschrijven, excluden, etcetera. Dit is over het algemeen goed te doen maar het kost meer moeite om het netjes te doen.  




  5.  

Door de strikte scheiding tussen functionaliteit en presentatie kunnen we vrij eenvoudig aan de Drupal-zijde de functionaliteit verpakken als Features en aan de React-kant de presentatielaag in componenten verpakken. De presentatielaag is daarmee volledig te vervangen zonder aan de functionaliteit laag te zitten en vice versa.

Nadelen

  1. Een grotere en complexere stack
    Het scheiden van onderdelen binnen een systeem (decomposition) heeft als voordeel dat ieder onderdeel an sich eenvoudiger en behapbaarder wordt. Een direct nadeel echter is dat wanneer het scheiden betekent dat er andere technieken gebruikt worden per onderdeel, de algehele stack groter en daarmee complexer wordt. 

    Dit is wat ons betreft vooral een theoretisch probleem; in de praktijk blijft dat dit in feite alleen maar voordelen geeft.  


  2. Standaard geen server-side rendering
    Server-side rendering heeft als voordeel dat een gebruiker een volledig opgebouwde pagina terug krijg wanneer een pagina bezocht wordt. Bij technieken als React ligt die verantwoordelijkheid standaard bij de browser: de server geeft de benodigde data terug om een pagina op te bouwen, de browser bouwt vervolgens deze pagina op. Een voordeel is dat de server hiervoor minder werk hoeft te verzetten, die verantwoordelijkheid ligt nu bij de browser. Hoewel na inladen de site in feite niet meer volledig geladen hoeft te worden (vanwege het Single Page Application principe), blijft een direct nadeel echter wel dat daardoor de site initieel trager aan kan voelen. 

    React heeft wel de mogelijkheid voor server-side rendering. Dit maakt het systeem echter aanzienlijk complexer door de behoefte aan nóg een proces dat op de server moet draaien.  


  3. Search Engine Optimisation
    SEO is de omvattende term voor het optimaliseren van de mate van vindbaarheid op zoekmachines. Hierin verwerkt zitten onderdelen als snelheid, structuur en opmaak, leesbaarheid en toegankelijkheid. De manier waarop dit bepaald wordt is gericht op de manier waarop websites opgebouwd worden aan de zijde van de server. Dit zorgt er voor dat sites die aan de browser zijde worden opgebouwd minder goed geïndexeerd kunnen worden, en dus een minder goede SEO score zullen geven.  




  4.  

Er zijn de afgelopen jaren veel ontwikkelingen gedaan, met name bij Google, om ook dergelijke websites te indexeren. Deze zorg is dus minder groot geworden. Voor sites als Bing, Facebook, LinkedIn en Twitter geldt echter dat hiervoor nauwelijks of geen ondersteuning is. Een eenvoudig voorbeeld hiervan is het delen van een link naar een website op Facebook. Er wordt op dit moment geen voorbeeld-weergave gegeven van sites die niet server-side rendered zijn.

Stappen naar een nog betere oplossing

Het systeem dat we op hebben gezet draait op dit moment succesvol op twee sites: de huidige website van Unc Inc zelf en de nieuwe website van Espero (in ontwikkeling). Maar intussen werken we ook aan de volgende stappen om de voordelen en toepasbaarheid verder te vergroten.

  1. Optimalisatie snelheid en SEO
    Wij hebben al de nodige stappen gezet om de vindbaarheid te vergroten door bijvoorbeeld voor een deel de pagina’s server-side te renderen. Dit leunt nu echter nog erg op Drupal waardoor we alsnog twee systemen gebruiken voor weergave, iets dat we in de toekomst graag anders zien. 

    Qua snelheid zijn er nog veel stappen te zetten. Google’s PageSpeed Insights geeft vaak nog een lagere score vanwege de langere “time to first interaction”, het resultaat  van het langere inladen van de pagina in de browser. Server-side rendering kan hier veel in verbeteren.  


  2. Vergroten herbruikbaarheid
    Aangezien we veel functionaliteit deels nieuw moeten ontwikkelen staat herbruikbaarheid voorop: alles wat we produceren binnen dit systeem moet opnieuw te gebruiken zijn bij toekomstige projecten.  


  3. Uitbreiding component library
    Een deel van de herbruikbaarheid zit hem in het opstellen van een component library: een soort catalogus van herbruikbare componenten, vergelijkbaar met bijvoorbeeld een styleguide. Componenten voor onderdelen als navigatie, pagina’s, categorieën, views, paragrafen en formulieren hebben we hier inmiddels al aan toegevoegd. De komende tijd gaan we library verder uitbreiden met componenten als search, facets, comments en in-page editing.  

Een headless CMS, iets voor jou?

Elke situatie is anders, elke website heeft weer zijn eigen wensen. Heb je behoefte aan een klankbord of zoek je een advies over de best mogelijke opzet voor jou? Neem dan contact met ons op, dan helpen we je graag op weg.