Html 5 Cache Features

March 20 20155 mins read html5 cache manifest

For several years, it became more and more important to make a web app running offline ( SPA by example ). Thanks to the HTML5 specs, many tools are awailable in two specific categories : Cache and Storage, let's see how to use them.

How HTML 5 Cache works ?

HTML5 Cache is a spec which let browser use resources (html, javascript, CSS, media files …etc), compatible with all modern browser from Internet Explorer 10, and can be configured by a file named: “manifest”.

Cache Manifest

To set the Cache configuration, we juste have to create the dedicated file : "cache.manifest" (for example), and reference it in all pages of the app like following:

<html manifest="site.manifest">

Good to know, the file extension can be anything as long as the file MIME type is specifically typed as : “text/cache-manifest”

About the content of the manifest, the first line must be the header “CACHE MANIFEST” and usually followed by a comment (with the “#” symbol) specifying the timestamp and the version of the manifest. This allow

elle peut être suivie d’une note en commentaire (grâce au symbole ) indiquant généralement un timestamp et la version actuelle du manifeste, ce qui permet au navigateur de détecter une modification et de revérifier les ressources.

La suite est divisée en plusieurs parties :

Voilà un exemple:

CACHE MANIFEST
# 18-03-2015 v1.1.7

CACHE:
index.html
content/site.css
app/application.js

NETWORK:
*

Explications

Lors de la première navigation sur le site, le navigateur va télécharger la page HTML comme il le ferait pour tout autre site web et si l’attribut manifest est renseigné le navigateur va alors récupérer le manifeste avec le chemin donné, puis requêter toutes les ressources spécifiées dans la section CACHE pour les stocker dans le cache avec le manifeste courant. Suite à ça le navigateur requêtera les autres ressources simplement avec ou sans fallback suivant votre configuration.

Attention, la sauvegarde du manifeste par le navigateur est automatique, il faut faire attention à ne pas référencer explicitement le manifeste dans la section CACHE, sinon le navigateur ne pourra jamais être conscient d’une nouvelle version.

Lorsque le navigateur accèdera une prochaine fois sur l’application web, il récupèrera automatiquement les ressources ( spécifiés dans la section CACHE ) depuis son cache sans les requêter au serveur, le manifeste coté serveur sera évalué pour vérifier si ce dernier a été modifié, d’où l’importance d’ajouter un en tête avec la version et/ou la date de mise à jour de vos ressources car même si vous ne modifiez pas la configuration de votre manifeste il est nécessaire de déclarer une nouvelle version de celui-ci pour que les clients téléchargent une nouvelle fois les ressources si vous avez effectué une modification sur l’une d’elles.

API Javascript Offline

Maintenant que nous connaissons le fonctionnement de la mise en cache, intéressons nous à l’API Javascript

ApplicationCache API

Les navigateurs ont aussi accès à l’objet window.applicationCache qui nous permet d’interagir avec le cache de l’application, cet objet nous met à disposition d’abord une suite d’évènements en fonction de l’état de la mise en cache :

L’objet nous permet aussi d’accéder à l’état de la mise en cache aussi via la propriété status et enfin expose les methodes update() pour lancer une la vérification d’une nouvelle version des ressources et swapCache() pour remplacer le cache avec un nouveau.

Exemple d’utilisation de l’API pour créer une progress-bar

Nous voulons créer une barre de progression qui indique l’état de chargement des ressources lors de l’initialisation d’une WebApp. Le processus est simple, afficher la progression dés la mise en cache des ressources, la faire progresser en fonction de l’avancement puis afficher le résultat si tout s’est bien passé ou si une erreur est survenue.

On implémente tout d’abord les methodes pour manipuler la barre de progression :

function showProgressBar() {
    var progressBar = "<div class='progress-bar'><progress id='progressBar' max='100' value='0'></progress><div class='message'>Mise en cache de l'application <span id='progress-message'></span></div></div>";
    $("body").append(progressBar );
    $(".progress-bar").fadeIn("slow");
    }
}
     
     
function updateProgressBar(loaded, total) {
    var pourcentage = Math.round(loaded / total * 100);
     
    $("#progressBar").attr("value", pourcentage);
    $("#progress-message").text(pourcentage + " %");
}
     
     
function cacheFailed() {
    hideProgressBar("Une erreur est survenu lors de la mise en cache de l'application");
}
     
function cacheSucceed() {
    hideProgressBar("L'application a été correctement mise en cache");
}

Et maintenant les abonnements aux évenements :

applicationCache.addEventListener('downloading', function (e) {
showProgressBar();
}, false);
 
applicationCache.addEventListener('progress', function (e) {
updateProgressBar(e.loaded, e.total);
}, false);
 
applicationCache.addEventListener('cached', function (e) {
cacheSucceed();
}, false);
 
applicationCache.addEventListener('updateready', function (e) {
appCache.swapCache();
}, false);
 
applicationCache.addEventListener('noupdate', function (e) {
cacheSucceed();
}, false);
 
applicationCache.addEventListener('error', function (e) {
cacheFailed();
}, false);

Voila le résultat :

result image

Evidement pour beaucoup de WebApp le chargement sera quasi instantané depuis un ordinateur, mais avoir une barre de chargement prend du sens pour une navigation depuis un mobile ou un device où la connexion est souvent plus lente.