Cees in Cyberspace

Tips & Scripts...

 

Headless WordPress de oplossing? Toch (nog) niet….

Headless WordPress de oplossing? Toch (nog) niet….

Alle WordPress gebruikers hebben wel eens iets mee gekregen over de traagheid of over de zogenaamde onveiligheid van WordPress. En natuurlijk zijn daar allerlei tools, scripts en plugins voor om dat te verhelpen, maar dat vereist toch diepere kennis en/of routinematig onderhoud.

Een andere oplossing zou zijn om de WordPress backend los te koppelen van “de voorkant”, de zogenaamde headless benadering. Je frontend bestaat dan niet meer uit PHP bestanden die WordPress functies aanroepen, maar uit maatwerk programmeercode die de WordPress REST API aanroepen.

Die REST API spuugt namelijk dezelfde inhoud uit, die de standaard PHP bestanden ook kunnen laten zien, zij het in een iets ander format. Maar de meeste items zijn publiekelijk beschikbaar, omdat ze toch ook al op de website getoond zouden worden.

Dus dat lijkt ideaal: het gebruikersgemak van de WordPress admin, maar met een “eigen” voorkant! In de praktijk lijkt de WordPress API er echter toch niet zo klaar voor te zijn als wordt beweerd.

Knappe URL’s

Je wilt natuurlijk op je (nieuwe) headless omgeving ook weer mooie URL’s aanroepen. Dus www.website.nl/dit-is-een-url/ in plaats van www.website.nl/?wordpressid=123. Want Google wordt blij als je woorden in je URL’s gebruikt en met standaard WordPress kan dat ook heel makkelijk via de Permalinks.

Als je op je headless omgeving een URL oproept, dan moet je echter meerdere calls doen om de juiste WordPress content te achterhalen. Als je hetzelfde voorbeeld www.website.nl/dit-is-een-url/ op wilt roepen in je browser, dan moet je de volgende stappen hebben genomen:

je moet er eerst achter komen wat voor soort WordPress item dit is om de juiste content erbij te kunnen halen.

Is het een page, post, custom post of een term, zoals een categorie? Want de posts, de pages, de custom post types en de categorieen in WordPress hebben allemaal eigen API endpoints. Dus je moet ze allemaal op verschillende manieren ophalen; er is geen “Laat me alle items zien”-methode helaas…

Wat is het?

Maar om erachter te komen aan welk soort item bovenstaande URL referereert, moet je eerst de slug (in dit geval: ‘dit-is-een-url‘) isoleren. Want die is uniek in WordPress en zou ons dus moeten kunnen vertellen bij welk item hij hoort.Maar hoe? De slug meesturen naar een endpoint in de WordPress API.

Helaas… zo’n endpoint bestaat (nog) niet en moet je dus zelf maken. Niet zo moeilijk, maar toch…

Als het vervolgens een post blijkt te zijn met het id 123, dan roep je het endpoint wpsite.nl/wp-json/wp/v2/posts/123 aan.
Is het een pagina, dan roep je wpsite.nl/wp-json/wp/v2/pages/123 aan.

Is het geen van beiden, dan zal de slug hoogstwaarschijnlijk die van een post categorie zijn (andere taxonomies laten we gemakshalve even achterwege…) Dus zou je in theorie dus het endpoint wpsite.nl/wp-json/wp/v2/categories/123 aanroepen. Maar dan krijg je de specificaties van de categorie met dat id.

En eigenlijk wil je natuurlijk de berichten in die desbetreffende categorie laten zien, dus zou je beter aanroepen: wpsite.nl/wp-json/wp/v2/posts/?categories=123.

Zou deze 3e call dan ook niets opleveren, dan is het waarschijnlijk een 404.

Maar… omdat je WordPress headless gebruikt en dus geen themes laadt, heb je dus ook geen 404-pagina om aan je bezoekers te laten zien. Die moet je zelf maken; dat kan in WordPress (zodat je gebruikers hem zelf kunnen onderhouden), maar ook gewoon in HTML.

Lang leve Gutenberg?

Als je een headless frontend wilt, maar je wilt ook perse Gutenberg in de admin (blijven) gebruiken, dan zit je aan de default WP REST API vast. Niet alleen gebruikt Gutenberg de API voor zijn block editor, de API is ook de enige manier om Gutenberg content in kant-en-klare HTML op te halen.

Want Gutenberg slaat de content op in je database met daartussen Gutenberg comments, die een browser niet zal begrijpen en/of zal negeren. Dus zal je in je frontend code moeten maken die deze comments interpreteert. Oftewel: je gaat Gutenberg nabouwen! En dat wil je niet….

… of een eigen API?

Dus: gebruik je de Classic Editor en stop je daarmee “pure” HTML in de database, dan zou ik aanraden wat custom API te maken met wat simpele endpoints en de default WP API uit te zetten. Dat is echt vele malen sneller, want… we zijn namelijk nog niet helemaal uit de problemen.

De standaard WordPress REST API is geen snelheidswonder, en als je plugins zoals Yoast of ACF toe gaat voegen (WooCommerce durfde ik niet eens te proberen), dan is het helemaal zeuren. Een caching plugin lost dit een tikkie op, maar nog steeds niet goed genoeg (of ik ben een zeurpiet, dat kan ook).

Ik heb er uiteindelijk voor gekozen om via een cronjob de API aan te spreken en vervolgens de output lokaal in JSON-files weg te schrijven. In mijn frontend kan ik dan rechtstreeks die lokale JSON gebruiken in plaats voor elk verzoek een API call te moeten doen.

Deze cronjob genereert de JSON files op het filesysteem van mijn frontend, maar je kunt ze natuurlijk ook door een maatwerk WordPress plugin aan laten maken bij elke keer dat je een post of een page opslaat.

Beide manieren zijn razendsnel, omdat je “tekstbestandjes” aanroept (niet oneerbiedig bedoeld!) in plaats van een API te initieren en te moeten wachten op output.

Met als bijkomend voordeel: je bent voor je website niet meer afhankelijk van WordPress. Dus mocht je een plugin hebben geupdated die opeens een foutmelding genereert of wordt je database traag, dan heb je daar in je frontend geen last van!

Zorg wel dat zo’n cronjob ook via een browser te starten is, dan kan je gebruiker ook zelf de boel updaten zonder de volgende run af te hoeven wachten!

Roept u maar!

Iemand met meer succes rechtstreekse WordPress API calls met Yoast en ACF geimplementeerd? Ik hoor het graag…