Neat Trick to Ensure You’re Serving Up “Fresh” Script and CSS in SharePoint

This is a cool trick devised by one of my colleagues at my current client. (Confidentiality reigns supreme in client situations. Suffice it to say that this wasn’t my bright idea, but I give credit to the real thinker.)

We were having trouble with caching of .js and .css files which we were deploying to the server file system. When we deployed new versions, end users’ browsers weren’t always picking them up. (If you’re storing your .js and .css files in Document Libraries in SharePoint, move on. There’s nothing interesting for you here.)

Originally, someone had written a little piece of code which would go out and check the modified date on each file every time a page was loaded which used it. The modified date was then used as a Query String parameter on the file load, like this: ?rev=YYYYMMDD. This was potentially worrysomely inefficient, as we were checking the modified date every single time. However, without this check, we weren’t assured that the “fresh” stuff was getting where it needed to go.

The bright idea was to add a little code to the global.asa file on each Web Application. (Yes, this needed to go on every Web App, and that means every Web App on every Web From End server.) A bit of a PITA to deploy, but it’s a one-time thing.

Here’s the code:

<!--Assembly Name="Microsoft.SharePoint-->
<!--Application Language="C#" Inherits="Microsoft.SharePoint.ApplicationRuntime.SPHttpApplication"-->
<script>// <![CDATA[

    protected void Application_Start(object sender, EventArgs e)
        Application["DateLoaded"] = String.Format("{0:MdyyyyHHmmss}", System.DateTime.Now);

    protected void Application_End(object sender, EventArgs e)

// ]]></script>

This simply creates a global variable called DateLoaded every time the Web App is started. We then use the DateLoaded variable in each link or script reference, like this:

<link rel="stylesheet" type="text/css" href="/_layouts/MyProject/Styles/custom.css?rev=<%#Application["DateLoaded"]%>" />

You might be thinking that this isn’t perfect, and you’d be right. We’re asking the browsers to load fresh copies of the .js and .css files every time we restart the Web Apps. However, the overhead on the server is almost nil. We don’t look at the files themselves on each file reference, we just serve them up. Since we are storing the files in the file system and deploying with WSPs, everytime we do do, the Web Apps are restarted, so we get a new value for the DateLoaded variable. This causes the browsers to reload the files, but we can be absolutely certain that the users are getting the right stuff.

No more “it doesn’t look like you’re telling me” conversations. Slick, eh?