Skip to main content

HTML Application Cache

Allow your web apps to work offline

The Application Cache essentially revolves around a "simple" cache manifest file (there's also a small, limited JavaScript API):

Example manifest file

CACHE MANIFEST
# v1.1

CACHE:

/about
/contact
/css/site.css
/img/logo.png
/js/site.js

NETWORK:
*
/application-form

FALLBACK:
/application-form /application-form-offline

Referencing a cache manifest file

You reference the manifest file in your page like this:

<html manifest="/manifest.appcache">

The name of the file can be anything you like but it must be served with: Content-Type:text/cache-manifest.

Manifest file format

The manifest file must start with CACHE MANIFEST.

In the example above you'll notice the second line is a comment (# v1.1), this is a regular comment but has a functional purpose. Browsers perform a "byte for byte" comparison of the manifest file to detect changes. If a change is found it will reload all the items in the manifest. A version comment is a nice way changing the file in order to get a browser to refresh the cache.

CACHE section

This is the default section for entries, all of which are explicitly cached. You should use this section to list ALL the files you want to cache.

It's ALL or nothing!

An important point to note is that ALL items in the manifest must successully download for the cache to be built. A single 404 will cause the process to be aborted and the cache will remain empty. It's all or nothing!

The page that contains the manifest reference is automatically added to the cache as a "master" entry, so you don't need to add it to the CACHE section.

NETWORK section

Use the NETWORK section to white-list resources that require a network connection.

It's common for sites to use the wildcard character * in order to white-list all resources that aren't in the cache.

Make sure you don't list resources in the CACHE section that you want to be in the NETWORK section, otherwise the cache will be used.

FALLBACK section

Use the FALLBACK section to specify a fallback to display when another resource is inaccessible. For example, a page listed in the NETWORK section may be inaccessible due to there being no connection.

Each entry lists two URIs: the first is the resource, the second is the fallback. The fallback resource is cached automatically, so no need to explicitly add it to the CACHE section.

Due to it's simplicity and high level nature, there are a number of quirks that you should know about.

Quirks

URIs are case sensitive

A request to /About will not be served a cached entry of /about.

Query strings

Be careful with QueryStrings too, a request to /about?who=me will not be served a cached entry of /about.

Hashes # don't change the URI so they can be used. They can be useful to pass data around, e.g. /about#?who=me. You can then parse the URI with JavaScript to get the data.

Cache first

Resources always come from the cache, even when you have a connection.

Application Cache ONLY updates when the manifest file changes

If you update a resource, you'll need to modify the manifest file in order to initiate an update, either by changing a URI or bump the version comment (as shown above).

You can't change the name of the manifest file because the page that contains the reference is itself cached!

HTTP Cache and Application Cache

The Application Cache is an additional cache, it's not an alternative the the HTTP cache. So, even when a manifest file is updated an HTTP cached version may be returned.

Non-cached resources won't load on a cached page

By default, non-cached resources won't load on a cached page but this is where the aforementioned wildcard in the NETWORK section can come into play:

NETWORK:
*

This ensures that a resource that isn't cached will be downloaded over the network.

Application Cache API

The API offers a number of statuses: UNCACHED, IDLE, CHECKING, DOWNLOADING, UPDATEREADY and OBSOLETE.

A useful status is UPDATEREADY. We can use the corresponding event to check if a new update has been downloaded.

window.applicationCache.addEventListener('updateready', onUpdateReady);

function onUpdateReady() {
	// There's a new version. Let's ask the user if they want to refresh the page.
	if (confirm('An update is available, do you want to refresh?')) {
        window.location.reload();
    }
}

// Check the current window.applicationCache.status in case the event was attached after the cache was updated.
if(window.applicationCache.status === window.applicationCache.UPDATEREADY) {
  onUpdateReady();
}

Local Storage is your friend

Local Storage can be used in conjunction with fallback pages to provide some more advanced functionality. But remember, JavaScript is required so you might be excluding some of your users.

An example would be to store data from a page when visited over the network and then retrieve it on a fallback page when there is no connection. The benefit of this is that the user can effectively build a cache of pages as they browse the website online.

Additional information and gotchas can be found at:

Hello, my name's Lee and I work as a full-stack web developer specialising in Microsoft ASP.NET technologies. I love using Umbraco and also MANAGED, my own interal CMS.

Contact me at lee.gunn@secretorange.co.uk

All skills

Contact

Get in touch to talk about your project or just ask me a question.

lee.gunn@secretorange.co.uk

Skype: lee_gunn