CSS caching voorkomen door versioning

Published on Feb 26, 2009

Het CSS caching probleem

Wanneer je een website aan het ontwikkelen bent, dan komt daar een heleboel gerefresh aan te pas. Telkens wanneer we een wijziging doorvoeren in onze code dienen we onze browser te verversen om de wijzigingen te kunnen zien. De F5 toets weet elke web designer ondertussen wel blindelings staan op zijn of haar toetsenbord en zelf willen we absoluut niet weten hoeveel keer we dagelijks op die toets drukken.

Wanneer we bijvoorbeeld een afbeelding bijwerken en deze nieuwe versie online plaatsen, dan dienen we soms zelfs onze website volledig (shifttoets+refreshknop in de browser) te verversen voor we deze bijgewerkte versie te zien krijgen. Hetzelfde geldt voor onze externe stylesheets of CSS-bestanden waarin we het uiterlijk van onze pagina's bepalen. Ook deze bestanden worden door de browser opgeslagen in het cachegeheugen om ze bij een volgend bezoek razendsnel te kunnen opvragen, zonder ze opnieuw van de webserver te moeten downloaden.

Voor ons web developers is dit natuurlijk de gewoonste zaak van de wereld en het constant verversen van onze pagina's hoort bij onze job. Maar wat gebeurt er wanneer je voor een klant aan het werken bent en hem of haar de link doorstuurt waar de laatste versie van de website staat.

Wanneer de klant in kwestie de site reeds in een eerder stadium bezocht heeft, wat heel waarschijnlijk is, dan is het best mogelijk dat deze niet de nieuwste versie van uw afbeeldingen of CSS te zien krijgt, wat op z'n minst tot verwarring zal leiden. Hetzelfde probleem zou zich kunnen voordoen wanneer we een grote layoutwijziging zouden aanbrengen aan een drukbezochte website. Een groot deel van de trouwe bezoekers zou een mislukte layout te zien krijgen dankzij CSS caching.

Een voorbeeld

Voor Yugsushi, een restaurant waarvoor wij de website beheren, dienden we onlangs een kleine wijziging door te voeren. Op de hoofdpagina moest een link komen naar de Wekelijkse special. Wanneer bezoekers op deze link klikken dienen ze in een soort van flyerformaat de huidige special te zien van het restaurant.

Op onderstaande schermafdruk ziet u de oorspronkelijke versie met daaronder de uiteindelijke versie zoals ze zichtbaar zou moeten zijn voor de klant én voor de bezoekers. Zoals u ziet gaat het slechts om een kleine aanpassing. Let op de nieuwe inhoud die we met een rode kader gemarkeerd hebben. Oorspronkelijke versie

Het CSS caching probleem

Voor deze kleine aanpassing hebben we niets meer gedaan dan wat xHTML toegevoegd met bijhorende CSS om de tekst en link op te maken. Onze externe stylesheet wordt als volgt gelinkt in alle pagina's:

link href="css/screen.css" rel="stylesheet" type="text/css"

Wanneer we dit CSS-bestand nu uitbreiden met nieuwe opmaak voor het kleine paragraafje dat we hebben toegevoegd aan de site, dan zitten onze frequente bezoekers (waaronder onze klant) met een probleem. Zij hebben de website namelijk al eerder bezocht waardoor hun slimme browser de stylesheet in cache heeft bewaard.

Hierdoor krijgen zij wel de paragraaf te zien met de nieuwe link, maar de browser herkent de stylesheet "screen.css" voor deze website en haalt razendsnel de cacheversie uit haar geheugen in plaats van de stylesheet van de server opnieuw op te vragen. Logisch misschien, maar wel vervelend, kijk maar naar het gedrocht dat onze frequente bezoekers te zien krijgen: Caching probleem Hetzelfde geldt voor de popup die we genereren wanneer een gebruiker op de link in onze paragraaf klikt. Deze popup is volledig kaal omdat de nieuwe CSS niet aanwezig is in het caching bestand. We krijgen al koude rillingen wanneer we bedenken dat bezoekers of onze klant dit te zien zou krijgen: Schermafdruk van dit project

Een mogelijke [foutieve] oplossing

Binnen de web development community werden al verschillende oplossingen naar voren geschoven om dit probleem te voorkomen. Eén van de mogelijke oplossingen die wordt aangereikt is Timestamping. Let op, dit is niét de beste manier en we raden u dan ook af om deze manier te gebruiken, maar het voorbeeld zet ons al wel op de goede weg.

link href="screen.css?<?php echo date('l jS \of F Y h:i:s A'); ?>" rel="stylesheet" type="text/css"

Wat resulteert in volgend resultaat:

link href="css/screen.css?Thursday 26th of February 2009 11:51:18 AM" rel="stylesheet" type="text/css"

Dit zorgt ervoor dat de browser op zoek gaat naar bestand screen.css met parameter "Thursday 26th of February 2009 11:51:18 AM". Deze laatste parameter zal elke seconde wijzigen, aangezien de gebruikte PHP-code steeds de huidige datum en tijd opvraagt. Hierdoor misleiden we de browser en zal hij telkens denken dat hij te maken heeft met een ongekende, nieuwe stylesheet. Opgelet: dit is niet de juiste manier om met caching om te gaan.

Aangezien de browser nu bij elk bezoek denkt dat hij een nieuwe stylesheet moet binnenhalen, zal dit de performance van onze website niet ten goede komen. Zelfs wanneer de stylesheet vanaf nu nooit meer gewijzigd wordt, zal geen enkele browser nog gebruik kunnen maken van caching voor onze stylesheet, zelfs niet bij meerdere bezoeken aan de website per dag. Stel dat de stylesheet de volgende drie maanden niet meer wordt gewijzigd missen we hier het voordeel van caching en zal de snelheid van onze website of applicatie nutteloos naar beneden gaan.

Een correcte oplossing

Een betere oplossing die gebruik maakt van caching wanneer het nuttig is én bezoekers toch steeds de meest recente stylesheet aanbiedt is de volgende.

link href="css/screen.css?<?php echo filectime('css/screen.css'); ?>" rel="stylesheet" type="text/css"

De gebruikte PHP-functie filectime() vraagt in een timestamp-formaat de datum en tijd op waarop het meegegeven bestand de laatste keer werd gewijzigd.

link href="css/screen.css?1235499781" rel="stylesheet" type="text/css"

Dit is een schitterende oplossing voor ons probleem aangezien deze wijzigingstijd enkel zal wijzigen wanneer wij een nieuwe versie van onze stylesheet online plaatsen. Wijzigen we de stylesheet niet, dan blijft de laatste wijzigingstijd onaangeroerd en kan de browser perfect gebruik maken van een eerder opgevraagde versie, zodat onze website sneller laadt voor frequente bezoekers.

Het uiteindelijke resultaat, altijd juist

Het uiteindelijke resultaat ziet er altijd uit zoals het moet zijn. Webdesigners tevreden, klant en bezoekers tevreden, zelfs de browser is tevreden. Happy caching! Laatste CSS versie automatisch actief!

No comments? But that’s like a Gin & Tonic without the ice?

I’ve removed the comments but you can shoot me a message on LinkedIn to keep the conversation going.