Skip and go to main content

Design & Technology April 25, 2019

In search of the best cache busting query string

Image

If you aren’t already, you should be cache busting your scripts and styles, and what better way to do that by making the url unique, clearing both the browser cache and any CDNs that are configured correctly. A good explanation of this can be found here.

But if we were to take this a step further and automate it, what would this look like, and what are our options?

Busting the cache based on version

If you’re doing any kind of serious project, you’re going to want some kind of automated versioning. We tend to use GitVersion for most of our projects here, which while it has a few foibles that can need ironing out depending on your continuous integration pipeline, i’d still recommend it as the defacto standard for generating out version numbers automatically.

Once you have a version number, it’s a case of reading that version number from somewhere and stamping that into a variable, then outputting your files based on that variable. Here’s a quick example:

public static string SiteVersion(this HtmlHelper helper)
{
return typeof(HTMLExtensions).Assembly.GetName().Version.ToString();
}

Then in your Razor or wherever you want to use it, you can just call it like this:

<script src="/_scripts/[email protected]()"></script>

This just gets you the version out of your assembly. This does require your build pipeline to be stamping the build onto your DLLs but apart from that it’s a pretty neat solution to the problem. It’s not my favourite though, for reasons i’ll go into below.

Image

Busting the cache based on file modified date

This one is pretty similar to busting based on version but doesn’t rely on you having versioning setup and generally has a lot less maintenance. However, it’s not as accurate as version based cache busting, or my preferred approach.

On top of that, if you have multiple content delivery servers, the timestamps could be different on each of them, which would mean browsers and CDNs would cache multiple versions of the same file.

With that said it’s very easy to get working, and if you have a very small project it might be a good bet for a quick way of doing it.

A good example is this stack overflow post.

Although there are a few problems with it on larger projects.

Image

Busting the cache based on git hash

This is my preferred approach, as your git hash should refer directly to the code itself, so there’s no chance of a collision between versions, and it aligns with repeatable builds, which is something I really like.

The only real downside to this one is that it’s a bit more computationally expensive than the others, so you likely want to cache it or use a singleton to generate it.

Here’s the example, it uses MSBuildGitHash which needs a small modification to your csproj so it can stamp the DLL with your git hash. After that you just need the following code to get the version out:

public static string VersionHash(this HtmlHelper helper)
{
var assembly = typeof(TheCurrentClassYou'reCallingFrom).Assembly;
var attributes = assembly.GetCustomAttributes<AssemblyMetadataAttribute>();
var hash = attributes.FirstOrDefault(a => a.Key == "GitHash")?.Value;
return hash?.Replace("-dirty", string.Empty);
}

Just replace the classname before the .Assembly call with your classname and you should be good to go.

Image

Questions? We are here to help!

Whoops!

If you’re reading this, you unfortunately can’t see the form that’s supposed to be here. You probably have an ad blocker installed. Switch the ad blocker off in order to see the form. Still encounter problems? Open this page in a different browser or get in contact with us: [email protected]