Caching in WordPress, iedereen doet het en bijna niemand weet precies wat het is of hoe het werkt. Vandaar dit artikel. Als je altijd al meer hebt willen weten over wat caching in WordPress is, lees dan gauw verder! Want caching is essentieel voor snelheid en performance, en performance is essentieel voor het succes van jouw website.
Wat is caching?
Voor we een duik nemen in de wereld van caching is het belangrijk om te weten: wat is cachen
(caching)? Stel je voor dat je voor een zaal vol mensen staat en hun vraagt
hoeveel is 456 x 96
Men begint te rekenen en na een paar minuten roept iemand: “43776!”
Als je nu dezelfde vraag (456×96) nogmaals stelt, roept de hele zaal direct 43776. En dát is caching: het antwoord is opgeslagen en direct beschikbaar. In dit geval in het brein.
Ditzelfde geldt ook voor een WordPress website: het resultaat van een HTTP-verzoek kan in een snellere opslaglocatie opgeslagen worden voor vrijwel directe beschikbaarheid. Bijvoorbeeld in het RAM-geheugen van web- of databaseserver, of op het bestandssysteem van de disk.
In dit caching artikel kan ik de termen request, verzoek en HTTP-verzoek door elkaar gebruiken. Ik bedoel steeds hetzelfde: een HTTP-verzoek van een bezoeker naar de website, bijvoorbeeld in de browser.
Dit artikel behandelt een aantal vormen van caching in WordPress. Je kunt de informatie gebruiken om een beter beeld van de cache-mogelijkheden te krijgen, en om de snelheid van jouw website te verbeteren.
Gebruik je geen WordPress? Geen nood! De meeste informatie geldt ook voor andere content management systemen (CMS’en): Joomla, Drupal, maar ook .NET zoals Umbraco of DNN. Je hebt dan alleen andere plugins en instellingen nodig. Handig! :-)
Op het eind van dit artikel geven we nog wat algemene tips over caching. Blijf dus lezen. Hier en daar kan het soms wat technisch worden, laat gerust een comment/reactie achter.
Het boek WordPress voor Dummies is geschreven door Lisa Sabin-Wilson, een bekend persoon binnen de WordPress-community. Zo weet je zeker dat je met dit boek goed zit. Deze handige gids is er voor beginners, maar ook voor degenen die al ervaring hebben met WordPress en er meer over willen leren.
Soorten cache
Voor WordPress – en iedere andere website of CMS – zijn in de regel vier verschillende soorten cache. We noemen ze in het kort:
- run-time cache
- object cache
- page cache
- fragment caching
Run-time cache
Een run-time cache bestaat voor zolang een bezoek duurt. In het geval van WordPress wordt PHP-code vertaald naar byte-code en in het geheugen van de webserver opgeslagen. Variabelen en waarden die vaker dan 1x voorkomen zijn direct beschikbaar.
Een WordPress voorbeeld is de query en het huidige post object die opgeslagen zijn in de $wp_query
en $post
globale PHP variabelen. Als er data van de huidige post nodig is hoeft de achterliggende MySQL-database niet weer geraadpleegd te worden. De informatie wordt uit de $post
variabele gehaald.
$post
Contains data from the current post in The Loop.
In een thema kun je bijvoorbeeld gebruiken:
<?php
global $post;
$author_id = $post->post_author;
echo $post->post_title;
?>
En deze informatie is dan op iedere plek in het thema-bestand beschikbaar, en voor dat ene request. Dit maakt de run-time cache een eenvoudige en efficiënte cache-strategie voor het kortstondig opslaan van informatie.
Maar de informatie moet voor iedere post/pagina opnieuw gegenereerd worden. En ook als de bezoeker terugkeert naar een al bekeken post/pagina.
Het nadeel van deze run-time cache is dus dat informatie alleen beschikbaar is gedurende het HTTP-verzoek. De cache wordt verwijderd als het request afgerond is. Ook al genereert de bezoeker content dat op meerdere pagina’s gebruikt zou kunnen worden (bijvoorbeeld een WordPress Sidebar Widget).
De data moet voor iedere request opnieuw gegenereerd worden. Dit probleem kun je tackelen met object caching.
Object cache
Door middel van object caching wordt data verplaatst naar een plek van waaruit het goedkoop en snel gehaald kan worden. Over het algemeen is dit in het RAM-geheugen van de webserver, door één of meerdere technologieën. Een object cache is persistent: gecachete data uit één HTTP-verzoek is beschikbaar gedurende alle vervolg verzoeken.
Populaire object caching engines zijn o.a Redis, Memcached, APC, de MySQL-database, of het bestandssysteem van de webserver. Daarnaast beschikt PHP standaard over OPcache, en op Windows Server is soms WinCache beschikbaar: een persistent memory object cache.
Psst, op Saotn.org leg ik uit hoe je de server configuratie PHP OPcache optimaliseert: How to optimize PHP OPcache configuration.
Als er van object caching gebruik wordt gemaakt is het essentieel dat dit goed gebeurt. Als object caching foutief geïmplementeerd is, én er andere vormen van caching worden gebruikt, dan kan dit heftige conflicten tot gevolg hebben met de rest van jouw cache-architectuur.
Je kunt gebruikmaken van WordPress’ Object Cache API voor het toevoegen aan, opvragen van en verwijderen uit de object cache:
function wp_cache_add( $key, $data, $group = '', $expire = 0 ) {
global $wp_object_cache;
return $wp_object_cache->add( $key, $data, $group, (int) $expire );
}
function wp_cache_get( $key, $group = '', $force = false, &$found = null ) {
global $wp_object_cache;
return $wp_object_cache->get( $key, $group, $force, $found );
}
function wp_cache_delete( $key, $group = '' ) {
global $wp_object_cache;
return $wp_object_cache->delete($key, $group);
}
Je vindt de code in wp-includes/cache.php.
Page cache
Page cache of full-page cache, omvat simpel gezegd het opslaan van de dynamisch gegenereerde content in statische HTML-bestanden. De naam zegt het eigenlijk al: de gehele post wordt als HTML opgeslagen.
Een webserver kan statische HTML-bestanden veel sneller serveren dan het steeds weer via PHP genereren van de content. Vaak zie je dan ook dat full-page caching in WordPress gebruikt wordt in combinatie met reverse proxies. Twee van die voorbeelden zijn Varnish en NGNIX, en die kunnen deze statische content nóg sneller kunnen serveren.
Echter, het nadeel van een dergelijke full-page cache is dat de cache plugin ervan uitgaat dat de content voor iedere bezoeker gelijk is. Oftewel: Jantje ziet precies dezelfde pagina als Gerard. Met een blog gaat dit nog wel, want die content is vaak statisch, maar als je een grote e-commerce webshop hebt wil je niet dat alle bezoekers dezelfde winkelmandjes hebben…
Met andere woorden: is jouw website echt statisch, dan is een full page cache een goede keuze. Heb je unieke content voor elke bezoeker? Dan vaak niet zo, want:
full-page cache gaat ervan uit dat iedere bezoeker dezelfde statische pagina te zien krijgt.
Vaak kun je hier nog beperkt omheen werken, bijvoorbeeld door niet te cachen als een bezoeker ingelogd is. Soms kun je zelf doorontwikkelen op een cache plugin om er eigen functionaliteit in te bouwen.
En dan werk je al gauw toe naar fragment caching. Maar eigenlijk is dat gewoon weer object caching.
Fragment cache
Door middel van fragment caching worden alleen delen van een post gecachet. Een fragment is een stukje van de post, maar niet de volledige post. Denk bijvoorbeeld aan een profiel widget, menu, pagina footer of een “related posts” lijst. Maar eigenlijk zijn dat weer objecten.
Over het algemeen gebruikt een fragment cache ook een object cache – zoals Memcached, APC, Redis, WinCache – als de opslag voor die fragmenten. (snap je het nog?) . Dus is een fragment cache niets anders dan een object cache, maar dan voor het opslaan van kleine delen van een post. Onderdelen die statisch zijn en niet vaak wijzigen.
Je leest meer over fragment caching in WordPress in Mark Jaquith’s blog.
Caching toepassen in WordPress
Nu je zo ongeveer weet wat caching inhoudt en welke vormen er zijn, wordt het tijd om hiervan delen te implementeren. “Jeej, let’s speed-up that website!“
In dit volgende deel gaan we in op object cache en page cache, omdat die correleren met de concepten in WordPress. Out-of-the-box is er geen fragment cache in WordPress, dus dat wordt verder niet behandeld.
WordPress Object Caching
WordPress implementeert een object cache door middel van twee mechanismen: transients en de WP_Object_Cache class. Het doel van object caching is om een persistente cache backend aan te bieden waarmee gecachete data beschikbaar is tussen requests. Zowel transients als de WP_Object_Cache
class kunnen deze persistentie bieden.
Een persistente cache is een cache die langer blijft bestaan (dan de huidige request).
Transients
Door middel van de WordPress Transients API kun je objecten in MySQL opslaan, en daaruit opvragen en verwijderen. Een transient is vergankelijk en heeft een instelbare expiratietijd. Standaard gebruikt deze transients cache de wp_options
tabel voor dataopslag.
Transients zijn een erg goede object cache optie in WordPress, omdat dit een cache-mogelijkheid geeft die geen configuratie vereist. Het nadeel van deze transients cache is de MySQL opslag zelf, wat over het algemeen wat trager is door extra round-trips tussen web- en databaseserver.
Vaak is het een betere strategie om de cache-opslag te scheiden van de algemene WordPress dataopslag (MySQL), om zo maximale efficiëntie te behalen uit beide dataopslag-locaties.
De WP_Object_Cache class
De WP_Object_Cache class is een PHP class die de opslaglocatie voor WordPress’ object cache definieert. Deze class kun je overschrijven met jouw eigen class, wat betekent dat je WordPress van iedere object cache-opslaglocatie gebruik kan laten maken.
Een aantal voorbeelden hiervan is: Redis, Memcached, WinCache, APC.
Het voordeel van het gebruiken van WP_Object_Cache
is voornamelijk performance. Door middel van deze class kun je WordPress gebruik laten maken van de beste cache engines die er zijn. Bijvoorbeeld, Redis en Memcached als object cache geven enorm snelle datatoegang, die ook nog makkelijk kunnen schalen naar meerdere servers.
Met WP_Object_Cache
kun je de cache ervaring in WordPress finetunen, waar de Transients API je erg weinig controle geeft over de specifieke cache engine.
Een bijkomend voordeel van WP_Object_Cache
is: code die de Transients API gebruikt, gebruikt automatisch de opslaglocatie van WP_Object_Cache
. Dus, als je een gefinetunede systeem met Memcached gebruikt en daarna een plugin installeert die de Transients API gebruikt, dan gebruikt deze plugin Memcached op de achtergrond in plaats van MySQL.
Neat! :)
Standaard is WP_Object_Cache
beschikbaar, maar is het alleen implementeert als run-time cache. Dit is omdat WordPress simpelweg niet kan bepalen of jij een andere cache-opslaglocatie beschikbaar hebt. Om jouw eigen object cache te maken moet je een bestand plaatsen in de map wp-content/
met de naam object-cache.php
. Als dit bestand bestaat, dan laadt WordPress deze automatisch en overschrijft daarmee de standaard WP_Object_Cache
class.
In het WordPress-jargon heet dit ook wel een WordPress drop-in plugin. Het advanced-cache.php
-bestand is een tweede drop-in pluginbestand (bedoeld voor full page cache).
In de WordPress Plugin catalogus vind je een aantal verschillende object-cache.php
bestanden voor verschillende cache engines.
Uiteraard zijn de object-cache-engines Redis, Memcached en APC beschikbaar bij Vevida. Wil jij meer weten over WordPress Hosting bij Vevida? Download dan de gratis WordPress website bouwen handleiding!
WordPress Page Caching
Vergelijkbaar met WP_Object_Cache
biedt WordPress een drop-in om een page cache de definiëren. Door een bestand met de naam advanced-cache.php
in de wp-content/
map te plaatsen kun je alle logica gerelateerd aan pagina caching maken.
Het generale idee voor de logica achter pagina caching is als volgt:
- Gebaseerd op de inkomende URL (
/mijn-eerste-post
), en wat andere informatie, kijk in de object- of pagina cache of er een gecachete versie van die pagina bestaat. - Als de gecachete versie van de opgevraagde pagina bestaat, serveer die uit de cache.
- Als de opgevraagde pagina niet in de cache bestaat, start output buffering (bijvoorbeeld door middel van PHP Output Control Functions), laadt de pagina vanuit WordPress, beëindig de output buffering, en sla het resultaat op voor vervolg requests.
Er zijn wat kleine nuances voor een pagina caching systeem, maar de logica hierboven definieert het meest gangbare systeem voor het generen van een pagina cache.
Mits goed uitgevoerd is het mooie van advanced-cache.php
dat een post of pagina slechts één keer door WordPress (PHP) gegenereerd hoeft te worden. Bij vervolg HTTP-verzoeken wordt het resultaat simpel uit de statische cache gehaald. De standaard persistente cache-opslaglocatie is wp-content/cache
.
Zijn jouw posts en pagina statisch, én herschrijf je HTTP-verzoeken goed d.m.v .htaccess
of web.config
URL Rewrite, dan kun je voor alle vervolgverzoeken PHP geheel omzeilen. Je leest hoe je dit doet in dit artikel …
Terwijl een volledige pagina cache met advanced-cache.php
één van de meest eenvoudige vormen van caching is in WordPress, kun je ook een reverse proxy aanpak met Varnish, NGINX of een hosted cache-oplossing gebruiken. We gaan verder niet in op deze oplossingen, omdat de configuratie vaak op server- of systeemniveau moet worden uitgevoerd en het weinig WordPress specifiek is. Maar we hebben het toch even benoemd als alternatief.
Een drietal veelgebruikte full page caching plugins voor WordPress zijn:
- WP-Super-Cache
- Cache Enabler
- WP Rocket (betaald/premium plugin)
- WP-Optimize
- W3 Total Cache
Combineer een full page cache met object cache voor een lighting fast WordPress website.
Caching Tips
Goed, nu weet je wat meer over caching in WordPress. Hierbij enkele punten van aandacht & advies, gebaseerd op onze eigen ervaringen bij Vevida.
- Wees niet afhankelijk van cache voor applicatiefunctionaliteit. Ontwikkel altijd met de aanname dat de cache 100% stuk is of niet aanwezig. Want ook zonder cache moet jouw WordPress-website goed functioneren, of niet? Ook moet jouw cache-oplossing altijd zèlf de cache kunnen regenereren.
- Gebruik cache als prestatieverbetering. Ook al moet jouw WordPress-website functioneren zonder cache, dat betekent niet dat de site ook goed en snel presteert. De cachelaag is om betere prestaties te bieden, niet functionaliteit.
- Test jouw site met caching in- en uitgeschakeld. Alleen dan kun je verifiëren of naar behoren functioneert. Afhankelijk van de gebruikte cachestrategie en cache-opslaglocatie kan dit eenvoudig of lastig zijn.
- Zet een vervaltijd (expiratietijd) voor elk object in de cache. In theorie moet je een gecachete object alleen verversen als deze gewijzigd is, maar je komt vrijwel zeker in een situatie waarin een probleem erg lastig te debuggen valt als je naar cache kijkt.
- Leer en ken het hosting- en cachesysteem dat je gebruikt. Verschillende cachestrategieën kunnen vaak alleen gebruikt worden als aan bepaalde voorwaarden is voldaan. Leer zoveel mogelijk over het hostingplatform, en ben je een beetje PHP-savvy: duik in de code.
- OPcode caches (waaronder PHP OPcache, WinCache) zorgen soms voor cache misses: ook al is het niet de bedoeling, je kijkt naar gecachete uitvoer. Ook na het herhaaldelijk herladen van de pagina. Zowel PHP OPcache als WinCache bieden functies om de cache geforceerd te invalideren. Die PHP-functies zijn:
Maak hiervoor een plugin. Zie mijn Must Use plugin “Clear PHP opcode caches” op Saotn.org als voorbeeld.
Herinner je het volgende nog bij Page Cache?
Is jouw website echt statisch, dan is een full page cache een goede keuze. Heb je unieke content voor elke bezoeker? Dan vaak niet zo.
Als je een WordPress WooCommerce webshop hebt kun je heel goed hieromheen werken met Javascript. Met een Javascript (jQuery of WP_Ajax) oplossing kun je heel goed een item toevoegen aan een winkelmandje wat zich in een page cache bevindt. Je vindt meer informatie in de WordPress Plugin Handbook
Conclusie Caching in WordPress
Je weet nu ongeveer wat caching is, waarvoor het dient en hoe je dit in WordPress gebruikt, kunt gebruiken of moet gebruiken. Je hebt ook geleerd dat als iemand jou WP-Super-Cache aanraadt, diegene jou aanraadt een full page caching plugin te gebruiken. Je weet nu wat dat inhoudt.
Hieronder een paar bonus tips.
Bonus Tip: Browser Cache en MySQL Query Cache
Naast al dit WordPress caching geweld zijn er nog twee belangrijke cachelocaties, namelijk:
- de MySQL query cache
- de browser van de bezoeker
MySQL Query Cache
MySQL’s query cache houdt in dat het resultaat van een query, wordt opgeslagen in het geheugen van de MySQL-server. Wordt dezelfde query binnen een bepaalde periode nog eens uitgevoerd, dan is het resultaat direct beschikbaar en hoeft MySQL niet de database te doorploegen.
Als klant en eindgebruiker heb je geen invloed op het beschikbaar zijn van MySQL query cache, maar bij Vevida is dit uiteraard ingeschakeld en goed geregeld.
Tegenwoordig is MySQL query-cache niet meer beschikbaar. Dit is opgenomen in het hierboven gelinkte artikel.
Browser Cache
We kennen het allemaal: we hebben een wijziging gemaakt op onze website, willen dat online bekijken en zien geen verschil. Na een keer de browser refreshen, tadaa!!, daar is de wijziging zichtbaar. Dat is browser cache (Internet Explorer noemt dit ook wel de tijdelijke internetbestanden, een naam die vaak wat bekender klinkt).
Een browser (Chrome, Firefox, Opera, Safari, Internet Explorer en Edge) slaat een website lokaal op, op de harde schijf van jouw computer. Die pagina is later weer te gebruiken als je dezelfde website bezoekt. Jouw browser hoef dan niet weer die website in zijn geheel op te vragen, maar kan het resultaat direct uit de lokale cache halen.
Simplistisch gezegd uiteraard, want er zijn altijd mitsen en maren.
Hoe voer je een hard refresh in Chrome uit?
Je kunt een browser eenvoudig vertellen dat een HTML-pagina, of andere statische bron (CSS, Javascript, afbeeldingen) in de lokale browser cache opgeslagen moet worden. Je doet dit met behulp van een web.config
of .htaccess
bestand, onze Klantenservice kan je hierover meer vertellen.
Gzip compressie voor statische- en dynamische bronnen:
Uitgaande van het Windows Server hostingplatform: standaard staat gzip compressie voor statische bronnen ingeschakeld. Voor dynamische bronnen (bijvoorbeeld PHP of ASP gegenereerde uitvoer) niet.
Je kunt dit zelf inschakelen in het web.config
bestand op jouw website, direct of door middel van IIS Manager. Neem in het web.config
bestand op:
<urlCompression
doStaticCompression="true"
doDynamicCompression="true"
/>
Of klik in IIS Manager door naar jouw website, dubbel klik Compression en vink Enable dynamic content compression aan.
In Linux/Apache kun je het volgende plaatsen in een .htaccess
-bestand om gzip compressie in WordPress aan te zetten:
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/xml
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE application/x-javascript
Of doe eens hip en zet Brotli compressie aan:
SetOutputFilter BROTLI_COMPRESS
Brotli is een compressie algoritme dat ontwikkeld is door Google.
WordPress Handleiding:
Download hier de gratis WordPress website bouwen handleiding!
WordPress Tips:
- WordPress optimaliseren
- WordPress plugins musthaves
- WordPress wp-login.php toegang beveiligen
- wp-config.php via FTP wijzigen
Dit artikel is deels vertaald vanuit van Zack Tollman’s post Core Caching Concepts in WordPress
Pingback: WordPress optimaliseren
Pingback: Leer PHP OPcache en realpath_cache_size optimaliseren
Optimized WordPress hosting is a subject on which a lot is written about. And therefore, this post is not about where to host your WordPress…