Hey browser, I'll tell you when to cache


David te Kloese

So you've created an update for your site. Fixed some CSS, updated some scripting, etc. Do the deployment and wait for the love and praises from the customer... Right?! "I don't see the change.". You'll respond with the common: "Did you try a different browser", did you clear your cache..." or the classic "Did you try turning it OFF an ON again". Often that does the trick. But isn't there an easier way to tell the browser to stop caching these files?

What happens

So actually most browsers try to help you speed up the page load. The browser does this by "remembering" resources the browser downloaded previously. For instance Images (logo), CSS and script files do not need to be downloaded again when a visitor navigates to another page.

How long these items need to be cached depends on your configuration, but quite often the Browser tries to help and does this purely on URL.

"I sees path, I has been there... I use cache". Handy when you don't set any cache headers, but deadly if you change your styling and nothing happens.
 

Solution

So what we decided to do is make sure all file paths are unique and updated when we change the file.

No we don't just start entering version numbers in the file names and on every page we include the resource. That would be too much work and chaos to manage.

What we do is create a virtual path with a version number based on a file's last modified date. And we insert this in our templates using a custom macro. Incoming requests are rewritten to point towards the correct file. This way it's easy to manage and the code does all the work!
 

Custom macro

How to create a custom macro you can find on Docs.Kentico.com.

First you need to create the code for your custom macro:



Code of custom Macro



Now in the header section of your template you can add the following (custom)macro:



Custom Macro in head section


This will render something similar to the following.


Rendered HTML with fingerprint



But wait a minute, this path doesn't exist! How do I tell the browser to resolve it back to its original path? For this we use a module in IIS called URL Rewrite.
 

URL Rewrite module

This module allows you to rewrite the URL from within IIS. After you've installed the module you can add rules using the web.config or directly from the module in IIS.



Rewrite rules in web.config


Rewrite rules in IIS



Most important is the pattern that must match the URL. In our case we always set resources in an /includes/ folder.

Than in the action properties section we use references ({R:#}) to the matched pattern to build up the final URL. Since my 2nd reference ((/v-[0-9]+/)) is the part where the modified date is stored we let this part out. And now IIS ends up with the correct URL and returns the correct file.

More info about syntax and features of the Rewrite module.
 

Testing

But does it work. Am I now able to tell the browser when to cache the file?

If you look at network monitoring tool (I used Fiddler) you can see the second call is getting a 304 status code. As in not modified, and the data can be loaded from cache.



Requests in Fiddler with status codes



When you update the file you can see the path is changed and your browser thinks it's a complete new file!