Offline cache is awesome! For certain things. For most regular web pages it is unfortunately not. Here is web developer’s most frequent use for the offline cache: make browser use cached version of the page when browser is offline but refresh it when it gets online. What could be simpler and more natural purpose for the OC? Well, unfortunately it wasn’t designed to work like this out of the box. Even when your browser goes online it will keep using the cached version “indefinitely” until the cache manifest is updated. So what do we do in this situation?
The tricky part is how do you update manifest. Most people just put something like
CACHE MANIFEST
#rev 13
/foo
/bar
/etc
Well, in this case if you change that “#rev 13” to “#rev 14” the browser will pull check the files in the manifest and pull the updated ones, which is what we need. So what could be easier, let’s just put a random number to this commented line every time! unfortunately some browsers (tested in Chrome) just refuse to cache page like this. Not sure how they do it and don’t have time to look at the sources, but it seems like if two pulls of the manifest immediately one after another return different values the browser just refuses to cache anything.
I played with different parameters and found that if you change the value of the manifest EVERY second that’s long enough to fool the browser and make it cache the page. Still if browser goes online in the next second our timer-based version number will make it pull the new version from the server. I’m with Node.js at the moment, so here is how this code looks in Javascript:
var cache_str = "CACHE MANIFEST\n" +
"#rev " + Math.floor( (new Date).getTime() / 1000 ) + "\n" +
"/foo\n"+
"/bar\n";
response.send(200, cache_str );
One uncool remaining part is that even if browser pulls new version of the page from the server it will do so AFTER it will render the page from cache, so you will need to reload the page TWICE. Sorry about so many allcaps, hate them too, but these are just very important things. It is easy to workaround with some jaascript and mayby a bit of AJAX, maybe I’ll explain how this could be done later.
This method was tested in Chrome and Mobile Safary and worked great. Not sure about the rest of the browser world.