Introduction
Il est de plus en plus important que les applications Web soient accessibles hors connexion. Oui, tous les navigateurs peuvent mettre en cache des pages et des ressources pendant de longues périodes s'ils y sont invités, mais ils peuvent supprimer des éléments individuels du cache à tout moment pour libérer de l'espace. Le HTML5 résout certains des problèmes liés à l'état hors connexion avec l'interface ApplicationCache. L'utilisation de l'interface de cache offre à votre application trois avantages:
- Navigation hors connexion : les utilisateurs peuvent parcourir l'intégralité de votre site lorsqu'ils sont hors connexion.
- Rapidité : les ressources proviennent directement du disque, sans passer par le réseau.
- Résilience : si votre site est en panne pour "maintenance" (par exemple, si quelqu'un casse accidentellement tout), vos utilisateurs bénéficieront de l'expérience hors connexion.
Le cache d'application (ou AppCache) permet au développeur de spécifier les fichiers que le navigateur doit mettre en cache et mettre à la disposition des utilisateurs hors connexion. Votre application se charge et fonctionne correctement, même si l'utilisateur appuie sur le bouton "Actualiser" lorsqu'il est hors connexion.
Fichier manifeste du cache
Le fichier manifeste de cache est un fichier texte simple qui liste les ressources que le navigateur doit mettre en cache pour un accès hors connexion.
Référencer un fichier manifeste
Pour activer le cache d'application pour une application, incluez l'attribut manifeste dans la balise html
du document:
<html manifest="example.appcache">
...
</html>
L'attribut manifest
doit être inclus sur chaque page de votre application Web que vous souhaitez mettre en cache. Le navigateur ne met pas en cache une page si elle ne contient pas l'attribut manifest
(sauf si elle est explicitement listée dans le fichier manifeste lui-même). Cela signifie que toute page à laquelle l'utilisateur accède qui inclut un manifest
sera implicitement ajoutée au cache de l'application.
Par conséquent, vous n'avez pas besoin de lister chaque page dans votre fichier manifeste. Si une page pointe vers un fichier manifeste, il n'existe aucun moyen d'empêcher son mise en cache.
Pour afficher les URL contrôlées par le cache d'application, accédez à about://://appcache-internals/ dans Chrome. Vous pouvez alors effacer les caches et afficher les entrées. Firefox propose des outils de développement similaires.
L'attribut manifest
peut pointer vers une URL absolue ou un chemin d'accès relatif, mais une URL absolue doit se trouver sous la même origine que l'application Web.
Un fichier manifeste peut avoir n'importe quelle extension, mais doit être diffusé avec le type mime approprié (voir ci-dessous).
<html manifest="http://www.example.com/example.mf">
...
</html>
Un fichier manifeste doit être diffusé avec le type mime text/cache-manifest
.
Vous devrez peut-être ajouter un type de fichier personnalisé à votre serveur Web ou à votre configuration .htaccess
.
Par exemple, pour diffuser ce type mime dans Apache, ajoutez la ligne suivante à votre fichier de configuration:
AddType text/cache-manifest .appcache
Vous pouvez également ajouter les éléments suivants dans votre fichier app.yaml dans Google App Engine:
- url: /mystaticdir/(.*\.appcache)
static_files: mystaticdir/\1
mime_type: text/cache-manifest
upload: mystaticdir/(.*\.appcache)
Cette exigence a été supprimée de la spécification il y a quelque temps et n'est plus requise par les dernières versions de Chrome, Safari et Firefox. Toutefois, vous aurez besoin du type mime pour que votre site fonctionne dans les anciens navigateurs et dans IE11.
Structure d'un fichier manifeste
Le fichier manifeste est un fichier distinct auquel vous associez l'attribut "manifest" de l'élément HTML. Un fichier manifeste simple se présente comme suit:
CACHE MANIFEST
index.html
stylesheet.css
images/logo.png
scripts/main.js
http://cdn.example.com/scripts/main.js
Cet exemple met en cache quatre fichiers sur la page qui spécifie ce fichier manifeste.
Voici quelques points à noter:
- La chaîne
CACHE MANIFEST
est la première ligne et est obligatoire. - Les fichiers peuvent provenir d'un autre domaine.
- Certains navigateurs imposent des restrictions sur la quantité de quota de stockage disponible pour votre application. Dans Chrome, par exemple, AppCache utilise un pool partagé de stockage TEMPORAIRE que d'autres API hors connexion peuvent partager. Si vous écrivez une application pour le Chrome Web Store, l'utilisation de
unlimitedStorage
supprime cette restriction. - Si le fichier manifeste lui-même renvoie un code 404 ou 410, le cache est supprimé.
- Si le fichier manifeste ou une ressource spécifiée dans celui-ci ne parvient pas à être téléchargé, l'ensemble du processus de mise à jour du cache échoue. En cas d'échec, le navigateur continuera d'utiliser l'ancien cache de l'application.
Prenons un exemple plus complexe:
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
Les lignes commençant par un # sont des lignes de commentaire, mais elles peuvent également servir à d'autres fins. Le cache d'une application n'est mis à jour que lorsque son fichier manifeste change. Par exemple, si vous modifiez une ressource image ou une fonction JavaScript, ces modifications ne seront pas mises en cache à nouveau. Vous devez modifier le fichier manifeste lui-même pour indiquer au navigateur d'actualiser les fichiers mis en cache.
Évitez d'utiliser un code temporel ou une chaîne aléatoire en constante évolution pour forcer les mises à jour à chaque fois. Le fichier manifeste est vérifié deux fois lors d'une mise à jour, une fois au début et une fois après la mise à jour de tous les fichiers mis en cache. Si le fichier manifeste a changé lors de la mise à jour, il est possible que le navigateur ait extrait certains fichiers d'une version et d'autres d'une autre. Il n'applique donc pas le cache et réessaie plus tard.
Bien que le cache soit mis à jour, le navigateur n'utilisera pas ces fichiers tant que la page n'a pas été actualisée, car les mises à jour ont lieu après le chargement de la page à partir de la version actuelle du cache.
Un fichier manifeste peut comporter trois sections distinctes: CACHE
, NETWORK
et FALLBACK
.
CACHE:
- Il s'agit de la section par défaut pour les entrées. Les fichiers listés sous cet en-tête (ou immédiatement après
CACHE MANIFEST
) seront mis en cache explicitement après leur téléchargement pour la première fois.NETWORK:
- Les fichiers listés dans cette section peuvent provenir du réseau s'ils ne se trouvent pas dans le cache. Sinon, le réseau n'est pas utilisé, même si l'utilisateur est en ligne. Vous pouvez ajouter des URL spécifiques à la liste d'autorisation ici, ou simplement "", ce qui autorise toutes les URL. La plupart des sites ont besoin de "".
FALLBACK:
- Section facultative spécifiant les pages de remplacement si une ressource est inaccessible. Le premier URI correspond à la ressource, le second à la solution de remplacement utilisée en cas d'échec ou d'erreur de la requête réseau. Les deux URI doivent provenir de la même origine que le fichier manifeste. Vous pouvez capturer des URL spécifiques, mais aussi des préfixes d'URL. "images/large/" capture les échecs des URL telles que "images/large/whatever/img.jpg".
Le fichier manifeste suivant définit une page "tout-en-un" (offline.html) qui s'affiche lorsque l'utilisateur tente d'accéder à la racine du site en mode hors connexion. Il déclare également que toutes les autres ressources (par exemple, celles d'un site distant) nécessitent une connexion Internet.
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
Mise à jour du cache
Une fois qu'une application est hors connexion, elle reste mise en cache jusqu'à ce qu'un des événements suivants se produise:
- L'utilisateur efface le stockage de données de son navigateur pour votre site.
- Le fichier manifeste est modifié. Remarque: La mise à jour d'un fichier listé dans le fichier manifeste ne signifie pas que le navigateur remettra en cache cette ressource. Le fichier manifeste lui-même doit être modifié.
État du cache
L'objet window.applicationCache
est votre accès programmatique au cache de l'application du navigateur.
Sa propriété status
est utile pour vérifier l'état actuel du cache:
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;
};
Pour rechercher par programmation des mises à jour du fichier manifeste, appelez d'abord applicationCache.update()
.
Cette opération tentera de mettre à jour le cache de l'utilisateur (ce qui nécessite que le fichier manifeste ait été modifié).
Enfin, lorsque applicationCache.status
est dans son état UPDATEREADY
, l'appel de applicationCache.swapCache()
remplace l'ancien cache par le nouveau.
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.
}
Bonne nouvelle: vous pouvez automatiser ce processus. Pour mettre à jour les utilisateurs vers la dernière version de votre site, définissez un écouteur pour surveiller l'événement updateready
au chargement de la page:
// 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);
Événements AppCache
Comme vous pouvez vous y attendre, d'autres événements sont exposés pour surveiller l'état du cache. Le navigateur déclenche des événements pour la progression du téléchargement, la mise à jour du cache de l'application et les conditions d'erreur, par exemple. L'extrait de code suivant configure des écouteurs d'événements pour chaque type d'événement de cache:
function handleCacheEvent(e) {
//...
}
function handleCacheError(e) {
alert('Error: Cache failed to update!');
};
// Fired after the first cache of the manifest.
appCache.addEventListener('cached', handleCacheEvent, false);
// Checking for an update. Always the first event fired in the sequence.
appCache.addEventListener('checking', handleCacheEvent, false);
// An update was found. The browser is fetching resources.
appCache.addEventListener('downloading', handleCacheEvent, false);
// The manifest returns 404 or 410, the download failed,
// or the manifest changed while the download was in progress.
appCache.addEventListener('error', handleCacheError, false);
// Fired after the first download of the manifest.
appCache.addEventListener('noupdate', handleCacheEvent, false);
// Fired if the manifest file returns a 404 or 410.
// This results in the application cache being deleted.
appCache.addEventListener('obsolete', handleCacheEvent, false);
// Fired for each resource listed in the manifest as it is being fetched.
appCache.addEventListener('progress', handleCacheEvent, false);
// Fired when the manifest resources have been newly redownloaded.
appCache.addEventListener('updateready', handleCacheEvent, false);
Si le fichier manifeste ou une ressource spécifiée dans celui-ci ne parvient pas à être téléchargé, l'ensemble de la mise à jour échoue. En cas de défaillance, le navigateur continuera d'utiliser l'ancien cache d'application.
Références
- Spécification de l'API ApplicationCache
- Application Cache is a douchebag (Le cache d'application est un con) : article sur les pièges et les problèmes liés à AppCache.