Offline App Development

… is a pain.

Mainly because once you add a file to the manifest, and thus to the browser’s app cache, you’re never sure if it’s getting updated. I spent most of last night and much of today just trying to get the browser to fetch the new version of html doc, and then the correct js file. Too bugged. It seems to be an issue primarily with Chrome & Chromium, but they are my primary development platform.

Anyway, if despite all the changes to manifest, restarting servers, clearing browser cache, the browser is still fetching old cached files, here’s a way out:

  1. Open a new tab in chrome/chromium and go to ‘chrome://appcache-internals/
  2. Clear all cached app resources
  3. Refresh the page to confirm there are no more cached app resources
  4. Refresh your test page – it should fetch everything from the server now

There’s another bit I learnt and implemented (though my implementation is pretty simplistic): Dynamic Cache Manifest.

Basically, instead of writing the application manifest, for offline app storage, by hand and changing it every time you change a file, let your server-side script do the work. What I’ve done is :

  1. Hand-wrote a cache manifest file but with a comment line that includes a django tag {{ts}}.
  2. Changed my app.yaml so that instead of serving the file directly, the request for it is sent to my server script.
  3. In the script I use the handwritten cache manifest and replace the ts tag with a random number.

What this ensures is that the browser is forced to fetch all elements in the app manifest every time because of the random number changing cache manifest on every fetch. This ensures that while I’m connected to the server and testing my js scripts, I get the latest versions every time. On the other hand, when I switch off the server and test the offline mode, the script still has resources available offline for rendering.

There is a lot more you can do here with the dynamic cache manifest rather than just plug-in a random number. I learnt this trick from this blog at Cube, and there are a couple more handy tricks being used there, so I suggest reading that resource.

Update: Seems like, as with script-initiated xhr requests, Chrome also makes multiple requests for the cache manifest from the server for every page load. When I use a randomizer function to send a ‘new’ cache manifest every time, this results in the two cache manifests being different to each other and thus Chrome doesn’t save any files. Not what I wanted, now? So, here’s a small change I made

previous randomizer: int(random.random()*10000)
new randomizer: time.strftime(‘%y%m%d%H%M’)

Now, instead of returning a new resource every time, I return a new resource every minute. This means that the two simultaneous requests that Chrome fires, will get the same cache manifest. But a page refresh/load later, will return a new cache manifest. It’s working so far :)
[Ofcourse, I know that there’s still a remote chance that the two requests will hit either side of the minute change. But the probability is small enough for me to take a chance.]