Offline apps with the Application Cache
Browsers already cache pages and resources, but they may evict anything from that cache at any time. The HTML5 ApplicationCache interface gives developers explicit control: list the files the browser should keep, and the app stays available offline. Using it brings three benefits: offline browsing for your full site, faster loads because resources come from disk instead of the network, and resilience when your server fails or is taken down for maintenance, since users ride out the outage on the cached experience.
The cache manifest
The cache manifest is a plain-text file listing the resources the browser should store for offline access. To enable it, add the manifest attribute to the html tag on every page you want cached:
<html manifest="example.appcache">
...
</html>
A page that includes the manifest attribute is implicitly added to the application cache; there is no way to prevent that page from being cached. There's also no need to list every page in the manifest itself. The attribute takes an absolute URL or relative path, but an absolute URL must be on the same origin as the application. The manifest file can have any extension, but must be served with the mime-type text/cache-manifest, which may require a custom type on your server. For Apache:
AddType text/cache-manifest .appcache
Or in Google App Engine's app.yaml:
- url: /mystaticdir/(.*\.appcache)
static_files: mystaticdir/\1
mime_type: text/cache-manifest
upload: mystaticdir/(.*\.appcache)
Recent versions of Chrome, Safari, and Firefox no longer require the correct mime-type, but older browsers and IE11 do.
Manifest structure and sections
A simple manifest starts with the required CACHE MANIFEST string on the first line, followed by one file path per line:
CACHE MANIFEST
index.html
stylesheet.css
images/logo.png
scripts/main.js
http://cdn.example.com/scripts/main.js
A few rules apply. Files can live on another domain. Browsers may cap the storage quota; in Chrome, AppCache draws on a shared pool of temporary storage alongside other offline APIs, though an app for the Chrome Web Store can remove that limit with unlimitedStorage. If the manifest itself fails with a 404 or 410, the cache is deleted. If the manifest or any listed resource fails to download, the whole cache update fails and the browser keeps the old cache.
Here is a more involved example:
CACHE MANIFEST
# 2010-06-18:v2
# Explicitly cached 'master entries'.
CACHE:
/favicon.ico
index.html
stylesheet.css
images/logo.png
scripts/main.js
# Resources that require the user to be online.
NETWORK:
*
# static.html will be served if main.py is inaccessible
# offline.jpg will be served in place of all images in images/large/
# offline.html will be served in place of all other .html files
FALLBACK:
/main.py /static.html
images/large/ images/offline.jpg
Lines beginning with # are comments. A comment can also serve a critical purpose: the browser updates the cache only when the manifest file changes. Editing an image or script alone won't trigger a re-cache; you must modify the manifest itself. Avoid a timestamp or random string that changes on every load, since that forces an update on every visit. The manifest is checked twice during an update, once at the start and once after all files update, so a manifest that changes mid-update can result in the browser fetching files from two different versions; in that case the update is discarded and retried later. Even after a successful update, the browser keeps using the old files until the next page refresh.
A manifest can declare three sections:
CACHE:— the default section. Files listed here, or immediately afterCACHE MANIFEST, are explicitly cached on first download.NETWORK:— files in this section come from the network if they aren't cached; otherwise the network is skipped even when the user is online. White-list specific URLs or use*to allow all traffic. Most sites want the wildcard.FALLBACK:— optional fallback pages for inaccessible resources. The first URI is the resource, the second is the offline replacement. Both must be same-origin with the manifest. You can match exact URLs or prefixes such asimages/large/, which also catchesimages/large/whatever/img.jpg.
This manifest serves a catch-all offline.html when the user tries to reach the site root offline, while requiring a network connection for everything else:
CACHE MANIFEST
# 2010-06-18:v3
# Explicitly cached entries
index.html
css/style.css
# offline.html will be displayed if the user is offline
FALLBACK:
/ /offline.html
# All other resources (e.g. sites) require the user to be online.
NETWORK:
*
# Additional resources to cache
CACHE:
images/logo1.png
images/logo2.png
images/logo3.png
Cache updates and programmatic control
A cached app stays offline until the user clears the site's stored data or the manifest file is edited. The browser exposes the cache state through window.applicationCache and its status property:
var appCache = window.applicationCache;
switch (appCache.status) {
case appCache.UNCACHED: // UNCACHED == 0
return 'UNCACHED';
break;
case appCache.IDLE: // IDLE == 1
return 'IDLE';
break;
case appCache.CHECKING: // CHECKING == 2
return 'CHECKING';
break;
case appCache.DOWNLOADING: // DOWNLOADING == 3
return 'DOWNLOADING';
break;
case appCache.UPDATEREADY: // UPDATEREADY == 4
return 'UPDATEREADY';
break;
case appCache.OBSOLETE: // OBSOLETE == 5
return 'OBSOLETE';
break;
default:
return 'UKNOWN CACHE STATUS';
break;
};
To check for manifest changes, call applicationCache.update(). When the status reaches UPDATEREADY, call applicationCache.swapCache() to switch to the new cache:
var appCache = window.applicationCache;
appCache.update(); // Attempt to update the user's cache.
...
if (appCache.status == window.applicationCache.UPDATEREADY) {
appCache.swapCache(); // The fetch was successful, swap in the new cache.
}
This can be automated by listening for the updateready event on page load:
// Check if a new cache is available on page load.
window.addEventListener('load', function(e) {
window.applicationCache.addEventListener('updateready', function(e) {
if (window.applicationCache.status == window.applicationCache.UPDATEREADY) {
// Browser downloaded a new app cache.
if (confirm('A new version of this site is available. Load it?')) {
window.location.reload();
}
} else {
// Manifest didn't changed. Nothing new to server.
}
}, false);
}, false);
Additional events fire for download progress, cache updates, and error conditions: checking, noupdate, downloading, progress, updateready, cached, obsolete, and error. A failed download of the manifest or any listed resource fails the entire update and the browser keeps using the existing cache.



