15 comments

[ 6.2 ms ] story [ 47.5 ms ] thread
This seems like a pretty bizarre solution. Careful design of updates to be resilient to ordering errors seems like the appropriate response here -- for instance, using the remote site like a content-addressible cache, rather than a name-addressible cache.

In response to a cache that provides only bare minimums for functionality, the author seems to be suggesting throwing away all the the cache logic that browser vendors have gone to implement for you, and instead rewriting one's own cache atop LocalStorage and IndexedDB. This seems like a pretty concerning reaction -- or am I simply misreading the author's conclusion?

Do you mind elaborating on content addressable vs name addressable? I did a quick google search on "name addressable cache" and did not find anything.
What he means is, instead of having a file you name

    myscript.js
you name it

    myscript-[sha1 hash of contents].js
and you set its cache header to expire at some improbably point in the far far future. If you should happen to update the contents of your script file- the sha1 hash will change, and thus its name and its cache entry will also change, in lockstep with its contents. The only fiddly part of this approach is you must also update all references to the new version of the file. If you're clever you can automate this with templates and build systems.

What this guarantees is that if your index.html and app cache manifest refer to myscript-[some specific sha1], you're guaranteed that the contents of the script are consistent with what that index.html file expects there.

Yes, that's standard deployment practice, but unfortunately with appcache, nothing links index.html to any specific version of the manifest. You can't even query it to see what version of the manifest you have. So you can end up with index.html trying to include a script of hashv1.js, but manifest has hashv2.js.

This can happen if clients are updating to app version 2 just as you are deploying v3. It's totally racy.

EDIT: I have a python script that proves it. It basically does new deployments (using only new, versioned .js files) while the browser reloads. I will be updating the post in the near future.

EDIT: Post updated with the test script and screenshot of what blows up.

what if the manifest.appcache is content addressable ? e.g. manifest-[version-number].appcache the appcache semantics are convoluted enough that I must admit I don't know what would happen. Would you visit index.html and it loads the old version of index.html linking to the old version of the cache manifest-- forever?

Perhaps the old version of the manifest gets a comment incremented to force the browser to update index.html? or some tricky javascript forces it? Either way it seems, naively like you could link an index.html version to a manifest version via the manifest's filename.

I see what you mean. But, at this point I'm not really interested in dicking around with it any more :-)
Ok everybody says the spec is broken.But the spec is not being fixed either.

The OP says : only put index.html in the appcache file.

But what about if I want my app to work offline,do I really need to go and shove everything in local storage?

So what's the point of appcache then ? and who went along with that spec at first place?

This specific issue infuriates me.It makes creating offline web app so complicated ,it's like the people writing the spec didnt want developpers to write offline apps.

Just fix the damn spec.

It is not that hard to just fix the few things that are broken in appcache. But it's more fun to start over with ServiceWorker (https://developer.mozilla.org/en-US/docs/Mozilla/Projects/So...).

I'm cautiously optimistic about SW, but sad that we didn't just fix the bugs however many years ago so that we at least had something that worked in the meantime.

I don't understand what need the appcache system fulfils. Within HTTP there is already a reasonable caching system. True, as mentioned in the post, the browser may occasionally clear the cache or elements of it; but that would be an argument for adding something like a `persist` flag to the `Cache-Control` header which would serve the exact same purpose, in addition to being backwards compatible with older browsers.
It seems to me that the point of appcache is to group the files that should be persisted into groups (not necessarily disjoint) that belong to different apps. This way, if the persisted files take up a lot of space, one can attribute that space to concrete apps.
The whole point is to enable the browser to be a full proper app platform- that includes enabling web apps to work OFFLINE. The behaviour of a browser without app cache is to fail to display content even if it is cached if your connection happens to be offline. the html5 app cache addresses that- and is the "standardised" alternative to google gears' local "offline" web server.
I had a play around in this area a few years ago. I had a tiny index.html that had just this script in the body.

  var s=localStorage["bootstrap"];
  if (s) {eval(s);} else {
    var t="But you are not carrying the axe!<br>";
	  t+='<a href="loadup.html">Get the Axe</a>';
	  document.body.innerHTML=t;
   }

http://fingswotidun.com/notanos/

Ultimately I found that I needed a server side because of URLs and the same-origin policy. There were just some things that browsers expected to fetch from a URL rather than have the data arrive by other means.

For a time I used a WebDav server to be a dumb server. Eventually the system evolved into https://github.com/Lerc/notanos Which uses it's own custom server https://github.com/Lerc/userserv which uses your unix login and statically serves files that your logged-in user is allowed to see.

AppCache is notoriously broken[0] (or really hard to work with), which is one of the reasons that the new ServiceWorker API was created[1]. ServiceWorker allows you to run a script in the background that can intercept network requests for specified paths, allowing you to create a pretty solid offline strategy (it also does some other interesting things, like push notifications, geofencing, and background sync).

There was a short video about ServiceWorker at the recent Google I/O that you can check out for an overview[2].

[0]: http://alistapart.com/article/application-cache-is-a-doucheb...

[1]: https://github.com/slightlyoff/ServiceWorker/blob/master/exp...

[2]: https://www.youtube.com/watch?v=4uQMl7mFB6g

AppCache is relatively new right? Is there no chance of pulling it out of the wild before making a headache in 20 years?
Well, it's "new" in the same way that HTML5 is new. It's been around for a few years.

The last time period that I played around with it was when iOS 3 was out, and it was horribly buggy (if you failed to download all of the things listed in the cache in the first go, then it would break and would refuse to ever try again). By iOS 4 it was less broken, but still weird.

Since it's been out there for a while it would probably be difficult to remove. Because of its brokenness I doubt that it ever got much usage, but there is probably some people out there that rely on it.

What I hope is that after ServiceWorker is better supported, someone can build out the old AppCache behaviour in JavaScript using the ServiceWorker APIs, and then we can use that for compatibility and remove AppCache from the browser itself.