random .NET and web development musings

You want your site to issue far-future cache expiry values for resources like CSS and JS to reduce bandwidth usage and decrease page load speed.

However, when you release new code, you want everyone to receive this a.s.a.p.
But how do you achieve this when they all have cached versions that are cache-valid for a week or more?

Here’s what I do.

Create yourself a class such as this:

public static class Cacher
{
	public static readonly string Value;

	static Cacher()
	{
		Value = DateTime.UtcNow.ToString("yyMMddHHmmssfff");
	}
}

Then, change your script and css tags from:

<link rel="Stylesheet" type="text/css" href="/assets/css/all.css" />

to:

<link rel="Stylesheet" type="text/css" href="/assets/css/<%: Cacher.Value %>/all.css" />

You can then use a mod_rewrite/asapi_rewrite rule to remove the value:

RewriteRule ^assets/css/[^/]+/all.css /assets/css/all.css [L,NC]

The reason you want the value in the path and not in the query string is that some caches refuse to cache content on URIs which include querys, regardless of the cache-control headers.

Alternatively, you could make the value be the current assembly version. It depends on your use-case.

4 COMMENTS
Victor Kornov
September 21, 2012
ad

Isn’t that going to reset the cache every app restart? That threw me off for a moment. Current assembly version would do it upon rebuild\redeploy.

September 21, 2012
ad

Yes, in my use case that’s what I want. It allows for emergency fixes on the fly – but lets not get into that 😉

Sen Jacob
February 6, 2013
ad

Is there any problem using like the following code? I feel this one as a simple solution.

static void resetCache()
{
Value = DateTime.UtcNow.Ticks;
}

and change style tags to

<link rel="Stylesheet" type="text/css" href="/assets/css/all.css?<% Value %>” />

February 6, 2013
ad

Unfortunately not, because there are lots of caches that ignore the query string. This is not correct behaviour, but its still what they do so you have to do it this way.

Post a comment