Tom Hamming
Tom Hamming

Reputation: 10981

How to update a web app without suffering cached CSS issues?

Say I've got a web app. I add some features to it, and those features require additions to some existing CSS files on my web server. I deploy my new features and CSS additions to my server, and they work great. Users visiting the site will probably have cached CSS in their browser, though, which means the new features will look broken/weird until either they manually refresh the page or their cache expires. The problem might be even worse if there's a cache server between my server and the user, in which case even a manual refresh won't help (I don't think).

Is there a common way to avoid this?

EDIT: I'm running on ASP.NET 4.0.

Upvotes: 6

Views: 2338

Answers (4)

Michael Piefel
Michael Piefel

Reputation: 19998

Of course I do not know your setup, as you do not mention it, but assuming you have a serlet container like Tomcat I would advise you to have a look at Jawr. Its purpose, from the web site: ‘Jawr is a tunable packaging solution for Javascript and CSS…’

It can do much more than what you asked for, but it also implements @scrappedcola’s idea fully automatically. The clients will see a URL containing a hash of the contents (something like scripts_A5F68E2.js) which has properties for caching set to eternity. Every time the contents change, the name changes as well, so the client will load the scripts anew.

Upvotes: 1

modebm
modebm

Reputation: 121

First of all it is common practice to append a version to the resources you load. This can be done by a version-parameter or by using frameworks like yawr.

If you prefer the first and use version control, it might be no bad idea to use the vcs revision string as version or - if you do release cycle use that version which may match to your changes best.

In PHP or Python you can generate a file containing the version string and refer to it in all required files. With Java or .NET you may want to have a compiled artifact in place.

I do not paste example code as of the missing of your setup.

Upvotes: 1

Rich Bradshaw
Rich Bradshaw

Reputation: 73045

I use the following with PHP in Apache:

function cssInclude($file) {
    $fileMTime = filemtime($_SERVER['DOCUMENT_ROOT']."/media/css/".$file.".css");
    return "<link rel=\"stylesheet\" href=\"/media/css/{$file}.{$fileMTime}.css\"
}

then in my <head>:

<?= cssInclude("style"); ?>

Then in my .htaccess:

RewriteEngine on
RewriteRule ^media/(js|css|img|font)/(.+)\.(\d+)\.(js|css|png|jpg|gif)$ /media/$1/$2.$4 [L]

Essentially what this does is make the link have the time in it. Originally I did it after the CSS using a ?, as in style.css?12313123, but found that some proxies didn't cache that as they assumed it was dynamic, making it slower (my work one messed it up for instance).

By writing it as style.123123123.css it appears as if it's a new file whenever it's modified, and caching works fine.

You'll noticed that in my .htaccess I'm also allowing myself to do it for different directories, and for a few different file formats – customise it as needed.

Of course, this means you are reading stuff from the filesystem, but if you have a caching layer in place then this is only done once per update.

Upvotes: 2

scrappedcola
scrappedcola

Reputation: 10572

You can add an arbitrary name value pair to the end of your css request and it will act as if it's not cached. For instance:

<link media="all" href="myhomepage.css?sid=1" type="text/css" rel="stylesheet">

When you make a change change the sid value.

Upvotes: 7

Related Questions