Cache Busting
Ensure your client has the latest version

Aug 06

Its great to cache static files such as images, CSS and JavaScript on the client. Its a huge performance improvement. But what happens when we need to invalidate that file as we have new ones. The way to get the client to retrieve a newer version is to use a different URL or ask the client to hit F5. Or follow Mads idea.

A while ago I would update my master page templates and any JavaScript references with myscript.js?v=2, then 3, then 4 for each release. This would ensure that end users would download the latest release and not use the local cached copy.

All good, but because it was a manual step sometimes human forgetfulness would kick in.

Mads

Mads is one of my favorite people. He currently works on the VS Web Essentials extension. He has a post on avoiding this problem.

You wrap your JavaScript in some server side code.
The code looks at your JavaScript file and generates a unique id based on the file last write time.
This id is used in a unique URL path to the JavaScript.
Then use URL Routing to get the correct file from the server.

This means that any time I do a deployment of my JavaScript files to my server the URL to the files is changed and thus the browser will download the new file. I now never have to worry about people running my site and using an outdated cached file.

I also don't have to manually update my master pages any more. Go check out his post for all the details.

The Sitefinity Version

When using this in Sitefinity you do need to take into account the /Sitefinity virtual path.

On the wrapper you need to enter the correct path of. '/Sitefinity/....'. But your code must use that App_Data path as its a physical lookup.

Simply update Mads FingerPrint code as below where I have changed the MapPath to add the App_Data path.

I have also added the code on my master page and the URL Routing below for reference. But check out Mads post as well.

I hope this helps you out.

<script src="<%=FingerPrint.Tag("/Sitefinity/WebsiteTemplates/MyTheme/js/foundation/FoundationBundle.min.js"%>"></script> 


public static class FingerPrint
{
    public static String Tag(String rootRelativePath)
    {
        if (HttpRuntime.Cache[rootRelativePath] == null)
        {
            String absolute = HostingEnvironment.MapPath("~/App_Data" + rootRelativePath);
 
            DateTime date = File.GetLastWriteTime(absolute);
            Int32 index = rootRelativePath.LastIndexOf('/');
 
            String result = rootRelativePath.Insert(index, "/v-" + date.Ticks);
            HttpRuntime.Cache.Insert(rootRelativePath, result, new CacheDependency(absolute));
        }
 
        return HttpRuntime.Cache[rootRelativePath] as String;
    }
}

<rule name="fingerprint">   
<
match url="([\S]+)(/v-[0-9]+/)([\S]+)" />   
<
action type="Rewrite" url="{R:1}/{R:3}" />
</
rule>

Extra

Also check out the Web Essentials bundling, so easy and compliments this service perfectly.


Darrin Robertson - Sitefinity Developer

Thanks for reading and feel free to comment
Darrin Robertson


Leave a comment
Load more comments

Make a Comment

Please type the code above

comment-avatar