Versnellen caching plugins je website? Soms wel… maar wees kritisch!
Het zal je waarschijnlijk niet ontgaan zijn, maar in de laatste tijd had ik met WordXPression een paar performance problemen.
WordXPression en Wear2Care zijn twee ondernemingen/websites in mijn eigendom. Wear2Care is het ‘concentratiepunt’ van mijn T-Shirt business. En WordXPression… tja, je kent WordXPression toch?
En omdat beide sites belangrijk zijn voor mij staan beide sites ook op een aparte VPS server. Maar samen wel op dezelfde.
En de laatste maanden zat het succes van Wear2Care de performance van WordXPression danig in de weg. Een belangrijk probleem voor mij was echter, is het de moeite waard om beide sites te splitsen -en daarmee mijn maandelijkse kosten nog meer te verhogen- of is het mogelijk om op een andere manier de performance te verbeteren.
Omdat ik best druk was met andere dingen, had dit probleem wel prioriteit, maar niet de allerhoogste. En gelukkig maar.
Want half augustus 2019 ging er iets goed mis met de WordXPression site. De site zelf was nog wel in de lucht, maar de pagina’s met blogs en blogposts, verantwoordelijk voor zo’n 80% van mijn verkeer, zagen er absoluut niet uit. Wanneer ik was ingelogd, was het geen probleem, maar zodra ik was uitgelogd, lagen mijn pagina’s compleet overhoop.
Wanneer een blogpost of pagina er ‘niet uitziet’ onder verschillende omstandigheden is een caching plugin meestal de grote boosdoener. Omdat een caching plugin nu eenmaal een pagina een ingelogde en niet ingelogde gebruikers op andere manieren laat zien. Dat leg ik verderop in dit artikel uit.
Caching was niet dat probleem!
Het probleem werd dus niet door de cache veroorzaakt. En ik ontdekte vrij snel wat het probleem was, en loste het op.
Wat ik echter vergat was de caching opnieuw aan te zetten. En tot mijn stomme verbazing, was mijn site ineens merkbaar sneller.
Dat is niet echt de bedoeling… dat je caching de site vertraagd. Ik besloot dus verder te testen en inderdaad bleek de W3 Total Cache plugin het snelheidsprobleem te veroorzaken.
Tijd dus om eens te kijken, of er een caching plugin is die betere resultaten oplevert.
Zoekend op het Internet heb ik een vijftal plugins gevonden, die inderdaad de site sneller maakten. Maar voor ik hier verder op inga, laten we eerst eens kijken, wat er nu eigenlijk gebeurt, wanneer iemand een webpagina opvraagt. En welke rol je cache hierin kan spelen.
Een webpagina is meer dan één document!
Voor jouw gevoel is een webpagina misschien één enkele pagina, één document dus. De realiteit is echter een stuk gecompliceerder. Een goed opgebouwde webpagina bestaat uit minstens twee bestanden. Eén HTML bestand en één CSS bestand. Het HTML bestand geeft de structuur van je pagina aan. Waar komen kopteksten, waar komt de tekst cursief te staan, waar komen opsommingen.
Je CSS bestand bepaalt de stijl van je pagina. Wat is het lettertype en de grootte van je kopteksten, wel lettertype gebruik je voor de broodtekst. Staan er bullets of ‘checkmarks’ in je opsommingen?
Maar met twee bestanden is het nog een behoorlijk saaie pagina. Alleen tekst. Om hier ook nog afbeeldingen aan toe te voegen, moet je nog meer bestanden toevoegen. Iedere afbeelding is een apart bestand. En wanneer er een lettertype wordt gebruikt, wat niet op jouw apparaat staat, wordt het bestand ook vaak via het Internet geladen.
WordPress maakt het nog ingewikkelder
Omdat we in WordPress alles dynamisch willen hebben, gebruiken we een programmeertaal. PHP. Wat PHP feitelijk doet is HTML naar jouw apparaat sturen. De inhoud van een PHP bestand kan je niet zien in je browser. Want op de server wordt dat al naar HTML omgezet. Dat omzetten kost tijd.
WordPress is een complex programma. Want je hebt niet alleen te maken met WordPress zelf, maar ook met de plugins. Bij iedere pagina die je laadt, zal een groot aantal plugins ook ‘meegeladen’ worden. Ook dat kost weer tijd.
Bovendien zal een plugin ook vaak output leveren die ook ‘gestyled’ moet worden. En daarvoor laadt die plugin dan ook weer zijn eigen stylesheets.
Je browser blijft maar vragen…
Stel, jij wilt de pagina https://wordxpression.nl/contact/ openen. Wanneer jij dit intikt in de browser, dan stuur je een HTTP verzoek wat er ongeveer uitziet als
GET https://wordxpression.nl/contact/
Daar begrijpt de server niet echt direct iets van. Want die ‘permalink’ is om de pagina er voor Google en mensen er aantrekkelijk uit te laten zien. WordPress zelf begrijpt dit verzoek veel beter als het het formaat
GET https://wordxpression.nl/index.php?...
heeft. Die drie puntjes geeft een hele serie parameters aan, die aan de URL meegegeven worden. Dus voor WordPress ook maar iets gaat doen, wordt de ‘mooie’ URL door de ‘rewrite’ module omgezet, naar een URL die WordPress begrijpt.
Vervolgens gaat de server aan de slag en roept de code aan, die de pagina /contact/ moet genereren.
… en vragen…
In de HTML code die je browser ontvangt, staat bijvoorbeeld ook nog, dat er afbeeldingen, JavaScript code en CSS code nodig is. Voor ieder bestand wat er nodig is, moet je browser een nieuw ‘GET request’, een nieuwe vraag aan de server stellen.
Eén enkele pagina in WordPress kan tientallen GET requests bevatten. En ieder request kost een beetje tijd.
Welke factoren bepalen je snelheid
De snelheid waarmee een pagina wordt opgebouwd, wordt door een aantal factoren bepaald. En in de moderne tijd, is de snelheid van je Internet verbinding meestal niet het grootste probleem.
Serveractiviteit
Eén heel belangrijke factor is de activiteit van de server. Is jouw site de enige site op die machine, of staan er tientallen andere op. Wordt die machine gedeeld met de database, of staat die op een aparte machine.
De drukte van je server is sterk bepalend voor de snelheid waarmee al die verzoeken afgehandeld kunnen worden.
Kwaliteit van de code
Een tweede belangrijke factor, die nauw te maken heeft met de server activiteit is de kwaliteit van de code. Hoe efficient zijn de plugins die jij gebruikt geprogrammeerd?
Ik heb in het verleden meer dan eens mijn ongenoegen laten horen met betrekking tot veel ‘page builders’.
Het probleem van de eerste generatie page builders zoals bijvoorbeeld Divi en Visual Composer/WP Bakery is dat ze de pagina opbouwen door middel van zogenaamde ‘shortcodes’. Iedere keer dat zo’n shortcode wordt aangeroepen, wordt er opnieuw een functieaanroep naar PHP gedaan. Een gemiddelde pagina gemaakt in WP Bakery kan soms 500-700 functies aanroepen alleen voor het opbouwen van de pagina. Dat kost veel tijd.
Een slecht geprogrammeerde plugin kan dan ook een behoorlijke belasting voor je server zijn en daarmee je pagina flink vertragen.
Maar ook als een plugin niet slecht is, iedere plugin die actief is, zal in ieder geval een paar regels code laden bij het opstarten, om aan WordPress te vertellen, wanneer de plugin in actie moet komen.
Het Netwerkverkeer
Een tweede oorzaak van vertraging kan het netwerkverkeer zijn. Hoewel we allemaal tegenwoordig heel snelle netwerkverbindingen hebben, is het toch goed om zuinig te zijn met je netwerkverkeer.
Om zuinig te kunnen zijn wordt daarom bijvoorbeeld niet ieder bestand iedere keer weer opnieuw verstuurd. Jouw browser bewaart de meest recent gebruikte bestanden. Wanneer een bestand wordt verzonden door de server, dan zal de server hier ook een soort ‘uiterste houdbaarheidsdatum’ aan geven. De browser zal alleen opnieuw om een bestand vragen aan de server, als deze datum verstreken is. Moet de pagina altijd vers opgevraagd worden, bijvoorbeeld omdat de gegevens sterk aan wijziging onderhevig kunnen zijn, dan krijgt het bestand een datum in het verleden mee. Daardoor wordt bij een volgend gebruik het bestand altijd opnieuw opgevraagd.
Het tekenen, ‘renderen’ door je browser.
De laatste factor die van toepassing is voor het opbouwen van de pagina is het renderen, het tekenen, van de pagina in je browser.
Hier valt eigenlijk weinig aan te optimaliseren. Hoe snel dit gebeurt, is helemaal afhankelijk van de snelheid van je computer en het aantal open applicaties. Hoe meer applicaties er open staan, hoe meer tijd het in principe duurt.
Wanneer je af en toe heel veel vensters van je browser open hebt staan, dan lijkt hij af en toe ‘vast te lopen’. Even reageert de computer niet meer, als je van tabblad of venster wilt verwisselen. Wat er dan aan de hand is, is dat je browser bezig is met ‘garbage collection’, het vrijmaken van geheugen, door het geheugen wat is bezet door tabs of vensters die al een tijdje niet gebruikt zijn.
Caching, twee niveaus
Wanneer jij als bezitter van een WordPress website wilt, dat je pagina snel op het scherm komt te staan, kan je op twee niveaus aan optimalisatie werken.
Browser caching
Eén niveau is het optimaliseren van browser caching. Dat kan je op twee manieren doen. Allereerst door te ‘vertellen’ aan de browser welke bestanden langer bewaard mogen worden. Hoe je dit doet ga ik later een keer op in.
De tweede manier is door gebruik te maken van reeds door andere partijen gehoste resources.
WordPress maakt bijvoorbeeld intensief gebruik van jQuery, een JavaScript library. Je kan deze library lokaal laden, vanaf je eigen server, maar er zijn ook verschillende ‘Content Delivery Networks’ die dit ook aanbieden.
Voor jou heeft dit als voordeel, dat het niet van je eigen server vandaan hoeft te komen. Het is gebruikelijk dat je van één server maar 6 bestanden gelijktijdig kan downloaden. Maar omdat bepaalde bestanden op andere servers staan, kunnen er meer gelijktijdig worden gedownload.
Voor je bezoeker heeft het als voordeel, dat wanneer hij (bijvoorbeeld) jQuery van een CDN laadt, hij dit recent al geladen kan hebben. Komt hij op jouw site dan ‘heeft’ hij dit dus al, en zal de pagina sneller worden opgebouwd.
Server caching
Server caching is veel complexer. In de meest eenvoudige vorm gebeurt het volgende. Jij vraagt een pagina op. Als er een caching plugin wordt gebruikt, dan zal bij de eerste keer de pagina op de gewone manier worden opgevraagd. En dat kost enige tijd.
Maar tijdens deze opvraging, wordt er direct ook een kopie van de pagina gemaakt. Helemaal HTML. Dus WordPress, PHP en de database hoeven helemaal niets te doen om jouw bezoeker die pagina te tonen. En dat is –zoals ik in een ander blogartikel over statische websites aangaf– retesnel.
En dat was hoe aanvankelijk WordPress Caching plugins werkten. Tot iemand bedacht, dat het nog sneller kon. En daar ging het allemaal fout.
Database Caching
Een briljant iemand bedacht ooit, dat we databases dikwijls dezelfde vragen stellen. Neem nu bijvoorbeeld de naam van deze website. WordXPression. Dat zie je boven iedere pagina staan. Maar wist je, dat iedere keer, dat deze pagina getoond wordt, er een vraag naar de database gaat ‘Hoe heet deze site ook al weer?’
Lijkt me nogal een verspilling van tijd en moeite, dacht je niet?
Wat nu, als we al die vragen die naar de database gaan bijhouden. Plus het antwoord hierop. Vinden we eenzelfde vraag, dan hoeven we niet naar de database toe om hem te stellen, maar kunnen we hem gelijk van de schijf inlezen. Scheelt behoorlijk wat tijd.
Geweldig idee. En de meeste grote cache plugins besloten dit de implementeren.
Object caching
Maar we kunnen nog een stap verder gaan. In WordPress ken je verschillende informatie ‘objecten’. Een voorbeeld is bijvoorbeeld een blogpost, een pagina en een product in WooCommerce. Zo’n object is een entiteit met bepaalde vaste kenmerken. Een blogpost heeft bijvoorbeeld een categorie en een aantal tags, een product een prijs en voorraad. Enzovoort.
Om de informatie voor zo’n object binnen te halen, moeten er heel wat vragen richting de database worden gestuurd. Maar eenmaal opgevraagd… waarom zou je dat nog een keer doen?
Dus de grote plugins stopten ook dit in hun cache.
Geweldig. Nu moet je website dus wel heel snel worden toch? Dus niet!
Wanneer is caching nuttig
Caching is alleen nuttig, wanneer de gegevens min of meer onveranderlijk zijn voor een bepaalde periode. Wanneer ik bijvoorbeeld beurskoersen zou presenteren, zouden mensen mij niet echt dankbaar zijn als ik de koersen van eergisteren zou laten zien.
Ook wordt het gecompliceerd, wanneer gegevens afhankelijk zijn van verschillende gebruikers. Wanneer ik inlog in mijn bank, dan zie ik graag mijn eigen saldo op dit moment. En niet mijn saldo van een week geleden. En al helemaal niet het saldo van meneer de Boer, die toevallig net voor mij zijn saldo bekeek.
Dat is een belangrijke reden, dat caching plugins alleen werken, wanneer je niet in de site bent ingelogd. Ben je eenmaal ingelogd in de site, dan krijg je de gegevens iedere keer vers gegenereerd getoond. Want de caching plugin kan niet bepalen wat wel en niet tijdkritisch of persoonsgebonden is.
Heb je dus bijvoorbeeld een Online Leeromgeving, dan zal caching wel de snelheid van bijvoorbeeld je salespagina verhogen, maar heeft iemand de training gekocht en is hij ingelogd, zal de caching plugin geen invloed op de snelheid hebben.
Database caching en object caching heeft alleen snelheidswinst op grote getalen!
Ik heb zo’n 20.000 bezoekers per maand, die samen zo’n 60.000 pagina’s bekijken. Dat is best veel. Maar volgens Google bestaat mijn site uit zo’n 1600 pagina’s. Als we dat voor het gemak van het rekenen even op 1.500 zetten, wil dit zeggen, dat gemiddeld iedere pagina 400x per maand wordt bekeken. Ofwel iets minder dan 14x per dag.
Natuurlijk wordt niet iedere pagina even vaak bekeken.
Maar zelfs op dit soort grote getallen, blijkt de overhead om object- en database cache te genereren dusdanig groter te zijn, dat feitelijk een caching plugin met deze opties aan je site niet versneld, maar juist vertraagd.
Er worden extra files gegenereerd en er wordt gezocht naar het bestaan van deze extra files zonder dat ze zo dikwijls nodig zijn, dat het ook echt snelheidswinst oplevert.
Zoek Fido, zoek!
Toen ik dit eenmaal goed door had, was het een kwestie van of de plugin beter configureren of op zoek gaan naar een andere plugin. Omdat ik het zelf wat te druk had, huurde ik een zeer gewaardeerde concullega waar ik vaker mee samenwerk in om uit te zoeken, wat nu de beste manier zou zijn om de WordXPression site sneller te tonen.
Natuurlijk begonnen we met het proberen W3C Total Cache te optimaliseren. Waarom zou je iets wegdoen, wat je al kent, alleen omdat je het verkeerd hebt ingesteld?
Toen database- en object caching uit was gezet, was de WordXPression website zo’n 40% sneller. Mooi meegenomen, maar nog steeds ver onder mijn norm.
We gaan dus nog dieper graven, en zoeken naar een nieuwe plugin.
Ik zal je niet lastig vallen met alle voors en tegens van de 5 verschillende plugins die zijn geëvalueerd voor dit onderzoek. Wat ik je wel wil vertellen, is de grote winnaar hier. Dat bleek een plugin te zijn met de totaal onaantrekkelijke naam ‘Cache Enabler‘.
En het aardige is… het is nog de makkelijkst te configureren plugin in deze categorie ook. Geen ellenlange schermen met de meest ingewikkelde parameters. Gewoon één scherm met een paar checkboxen en keuzelijstjes. En dat is voldoende.
Cache Enabler
Zoals al aangegeven, deze plugin is belachelijk eenvoudig in het gebruik. Maar super effectief. Om je een indruk te geven. Oorspronkelijk werd -voor ik ontdekte, dat W3C Total Cache de site feitelijk vertraagde, een pagina opgebouwd in gemiddeld 10 seconden. Veel te langzaam dus. Na het uitzetten van de plugin, werd de opbouw van de pagina behoorlijk sneller. Gemiddeld 7 seconden. Maar nog steeds onacceptabel.
Toen mijn goede vriend Arkady aan het testen was geslagen met W3C Total Cache, wist hij deze tijd tot 4.5 seconden terug te brengen. Maar nog steeds onacceptabel traag.
Met Cache Enabler nu actief wordt een gecachte pagina in een tijd van tussen de 0.19 en 0.67 seconden, gemiddeld 0.27 seconden, geladen. Of met andere woorden, de HTML wordt sneller geladen, dan je browser in staat is hem te renderen.
Is een pagina nog niet gecacht, dan is de tijd nog steeds gemiddeld 7 seconden.
De userinterface
Ok… weinig spectaculair.
Cache Expiry
Hier geef je aan hoe lang de cache geldig moet zijn. Hier is eigenlijk geen goede regel voor te geven, omdat iedere keuze zijn voor- en nadelen heeft. Het is je vast wel opgevallen, dat ik veel gebruik maak van het tonen van min of meer ‘willekeurige’ rode balken in mijn blogposts, waar ik titels van gerelateerde andere blogposts laat zien. Dat leidt tot heel wat ‘doorklikken’.
Een deel van het succes hiervan is ook de ‘willekeur’ waarin de titels getoond worden. Zowel oude als nieuwe titels worden getoond.
Door deze pagina’s te cachen zullen deze titels niet meer wisselen. Je zal gewoon, tot de cache weer leeg gemaakt is, bij die specifieke blogpost dezelfde titels blijven zien.
Kortom, allerlei dingen die je doet om ‘willekeurige content’ te tonen is ineens een stuk minder willekeurig geworden.
Zet ik de tijd echter een stuk korter, dan krijg je wel weer de afwisseling in titels te zien, maar lever je in op de snelheid.
In de praktijk werk ik bijna dagelijks aan mijn site. En zoals je aan de andere instellingen kan zien, op het moment, dat er een nieuwe blogpost wordt geplaatst, een bestaande aangepast, of een pagina wat verandert, worden de caches toch geleegd.
Ik heb de tijd op 48 uur staan, vanuit het idee, dat ik ’s avonds toch meestal aan mijn site werk. Dus dan wordt de content sowieso opnieuw gegenereerd. Maar doe ik het een keer niet, dan blijft de bezoeker niet eeuwig naar dezelfde ‘lees meer’ suggesties kijken.
Cache behavior
Hier geef je aan, wanneer de cache geleegd moet worden. Als extra kan je hier aangeven, dat je gebruik wilt maken van WebP support. Doe je dat, dan worden je afbeeldingen geconverteerd naar het WebP formaat, een relatief nieuw formaat voor afbeeldingen, wat nog niet door alle browsers wordt ondersteund, maar wel veel sneller laadt.
Ondersteund je browser het niet, zal er gewoon een PNG of JPG bestand worden getoond. De integratie met WebP is niet gratis.
Eigenlijk zou ik je aanbevelen om alle instellingen onder dit kopje exact zo in te stellen als ik het gedaan heb. Tenzij je geen WebP support wenst. Die zet je dan uit.
Cache exclusions
Hier kan je aangeven welke bestandspaden niet gecached moeten worden. De makkelijkste manier om dit te doen, is door dit in te vullen in het veld ‘ID’s’. Wanneer je bijvoorbeeld kijkt naar WooCommerce, dan wil je de pagina’s van het afrekenproces bijvoorbeeld niet gecachet hebben.
Stel dat de ID’s van die pagina’s 5, 6 en 7 zouden zijn, dan vul je 5,6,7 in.
Cache inclusions
De cache inclusions geven aan, wanneer een pagina niet vanuit de cache moet worden bediend. Stel, je hebt een plugin die de resultaten van een campagne bijhoudt door middel van UTM variabelen. Dan wil je natuurlijk ook, dat deze variabelen daadwerkelijk geëvalueerd worden. Dus moet toch de niet gecachte versie gebruikt worden.
Standaard worden UTM variabelen herkend en dan zal er niet vanuit de cache bediend worden.
Cache minification
Hier geef je aan welke bestanden ‘minified’ moeten worden. Dus gestript van alle spaties, waardoor ze minder leesbaar, maar wel een stuk kleiner worden.
Wanneer je zoals ik Elementor gebruikt, kan je het best kiezen voor ‘HTML’. Gebruik je geen Elementor, probeer ‘HTML & JavaScript’. Levert dat rommelige pagina’s op, ga dan naar HTML of ‘Disabled’.
De cache testen
En dan wil je natuurlijk de cache testen. Je klikt op een pagina… en hij blijft even traag. O ja! Wilko had gezegd, dat de eerste keer de pagina traag blijft! Nog een keer klikken. En hij is nog steeds traag.
Wat doe je fout?
Waarschijnlijk ben je nog ingelogd. De beste manier om je cache te testen is je browser in een ‘Privé’ window (Incognito mode/Privacy mode/Silent mode… afhankelijk van je browser) te openen. En nu zal je zien, dat de eerste keer dat je pagina geklikt wordt, er nog niet verschil in zit… maar na enkele pagina’s geklikt te hebben en dan weer diezelfde pagina aan te klikken is hij ineens razendsnel.
Om je een indruk te geven, de grafiek van de productieserver van WordXPression in de afgelopen dagen.
Wat je hier ziet is de gemiddelde tijd om de pagina’s te genereren. Het gaat hier met name om de laatste vier punten. Op de eerste en tweede dag dat ik Cache Enabler had geïnstalleerd (gemiddelde tijd 3.8 seconden) was ik op de site aan het werk met het aanpassen van pagina’s. En dan wordt natuurlijk met de instellingen zoals ik deze heb, de cache geleegd en moeten pagina’s opnieuw gegenereerd worden. Dat kost extra tijd.
En wanneer je een groot aantal waarden hebt in de buurt van 0.2-0.6 dan is ineens ‘6 seconden’ een enorme piek, die het gemiddelde fiks omhoog haalt.
De laatste punt is op een dag waar ik helemaal niets aan de site heb aangepast. De gemiddelde generatietijd van een pagina is hier minder dan 1.5 seconden. De meest voorkomende tijd is echter 0.3 seconden.
Een geweldige snelheidsverbetering dus.
Enkele nadelen
Natuurlijk is het niet alles goud wat er blinkt. En deze plugin schiet op een aantal punten in mijn optiek enigszins te kort. Ik weet niet of er een goede reden is om het niet te doen, maar de meeste cache plugins waar ik mee gewerkt heb, hebben een mogelijkheid om pagina’s te ‘preloaden’.
Want je hebt natuurlijk het liefst, dat ook die ene bezoeker die als eerste de pagina laadt, een fatsoenlijke responsetijd heeft. De meeste caching plugins bieden dan ook de optie om alvast een groot aantal pagina’s automatisch te laten creëren.
Dit nadeel kan je echter omzeilen. Als je je webstatistieken regelmatig raadpleegt -en dat doe je natuurlijk- dan weet je zonder enige twijfel, wat je meest bezochte pagina’s zijn.
Als jij er nu voor zorgt, dat jij degene bent, die na het legen van de cache als eerste die pagina bezoekt -natuurlijk als je niet bent ingelogd- dan krijgen jouw bezoekers uitsluitend de snelle versie van jouw meest populaire pagina’s.
Conclusie
Tja. Wat kan ik zeggen? Ik had nooit verwacht mijn site zo snel te kunnen krijgen als hij nu is, zonder een flinke investering te moeten doen in een nieuw VPS. En jij zal het ook merken… de site is aanzienlijk sneller geworden. En het allerleukst is misschien wel, dat dit met een plugin is, waar je bijna niets aan hoeft te configureren.
Ik deze dus van harte aanbevelen.