Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to properly invalidate an HTML5 Cache Manifest for online/offline web apps?

I'm currently using a Cache Manifest (as described here). This effectively makes the necessary resources to run the application available when the user is offline.

Unfortunately, it works a little too well.

After the cache manifest is loaded, Firefox 3.5+ caches all of the resources explicitly referenced in the cache manifest. However, if a file on the server is updated and the user tries force-refreshing the page while online (including the cache-manifest itself), Firefox will absolutely refuse to fetch anything. The application remains completely frozen at the last point it was cached. Questions:

  1. I want Firefox to effectively only rely on the cached resources when the network connection fails. I've tried using the FALLBACK block, but to no avail. Is this even possible?
  2. If #1 is not possible, is it possible for the user to force-refresh a page and bypass this cache (ctrl-F5 doesn't do it and neither does clearing the browser's cache, shockingly) short of clearing their private data? Alternatively, does the cache-manifest mechanism support expiry headers and is its behavior with respect to this documented anywhere?
like image 997
Justin Searls Avatar asked Nov 11 '09 14:11

Justin Searls


People also ask

What allows HTML5 applications to work in an offline state?

HTML5 introduces application cache, which means that a web application is cached, and accessible without an internet connection. Application cache gives an application three advantages: Offline browsing - users can use the application when they're offline.

How does HTML 5 implement application cache?

Application Cache in HTML5: The current version of HTML5 introduces application cache, which means that a web application is cached, and accessible without an internet connection. Now we can make an offline web application that will run without an internet connection by just creating a manifest file in our application.

What does cache do in manifest file?

The CACHE section contains files you want to load and store on the user's machine. The first time the user loads your app, the browser will store all the files in the CACHE section of your app cache manifest.

How do I use HTML cache?

To use cache-control in HTML, you use the meta tag, e.g. The value in the content field is defined as one of the four values below. HTTP 1.1. Allowed values = PUBLIC | PRIVATE | NO-CACHE | NO-STORE.


1 Answers

I think I've got this figured out: if there's an error in one's cache-manifest (say, a referenced file does not exist), then Firefox completely will stop processing anything applicationCache related. Meaning, it won't update anything in your cache, including your cached cache-manifest.

To uncover that this was the issue, I borrowed some code from Mozilla and dropped this into a new (non-cached) HTML file in my application. The final message logged stated that there might be a problem in my cache-manifest, and sure enough there was (a missing file).

 // Convenience array of status values var cacheStatusValues = [];  cacheStatusValues[0] = 'uncached';  cacheStatusValues[1] = 'idle';  cacheStatusValues[2] = 'checking';  cacheStatusValues[3] = 'downloading';  cacheStatusValues[4] = 'updateready';  cacheStatusValues[5] = 'obsolete';   // Listeners for all possible events  var cache = window.applicationCache;  cache.addEventListener('cached', logEvent, false);  cache.addEventListener('checking', logEvent, false);  cache.addEventListener('downloading', logEvent, false);  cache.addEventListener('error', logEvent, false);  cache.addEventListener('noupdate', logEvent, false);  cache.addEventListener('obsolete', logEvent, false);  cache.addEventListener('progress', logEvent, false);  cache.addEventListener('updateready', logEvent, false);   // Log every event to the console  function logEvent(e) {      var online, status, type, message;      online = (isOnline()) ? 'yes' : 'no';      status = cacheStatusValues[cache.status];      type = e.type;      message = 'online: ' + online;      message+= ', event: ' + type;      message+= ', status: ' + status;      if (type == 'error' && navigator.onLine) {          message+= ' There was an unknown error, check your Cache Manifest.';      }      log('
'+message); } function log(s) { alert(s); } function isOnline() { return navigator.onLine; } if (!$('html').attr('manifest')) { log('No Cache Manifest listed on the tag.') } // Swap in newly download files when update is ready cache.addEventListener('updateready', function(e){ // Don't perform "swap" if this is the first cache if (cacheStatusValues[cache.status] != 'idle') { cache.swapCache(); log('Swapped/updated the Cache Manifest.'); } } , false); // These two functions check for updates to the manifest file function checkForUpdates(){ cache.update(); } function autoCheckForUpdates(){ setInterval(function(){cache.update()}, 10000); } return { isOnline: isOnline, checkForUpdates: checkForUpdates, autoCheckForUpdates: autoCheckForUpdates }

This was certainly helpful, but I should definitely request a feature from Mozilla that prints out malformed cache-manifests at least to the Error Console. It shouldn't require custom code to attach to these events to diagnose an issue as trivial as a renamed file.

like image 68
Justin Searls Avatar answered Sep 17 '22 13:09

Justin Searls