Leitfaden für die ersten Schritte bei der Verwendung des Anwendungscaches

HTML5 Rocks

Einführung

Es wird immer wichtiger, dass webbasierte Anwendungen offline zugänglich sind. In der Tat verfügen alle Browser über Caching-Mechanismen, allerdings sind diese unzuverlässig und funktionieren nicht immer erwartungsgemäß. HTML5 beseitigt durch die ApplicationCache-Schnittstelle einige der Ärgernisse beim Offline-Zugriff.

Die Verwendung der Cache-Schnittstelle sorgt in der Anwendung für drei Vorteile:

  1. Offline-Surfen: Die Nutzer können auch offline durch Ihre gesamte Website navigieren.
  2. Geschwindigkeit: Im Cache gespeicherte Ressourcen liegen lokal vor und werden daher schneller geladen.
  3. Geringere Serverlast: Der Browser lädt vom Server nur die Ressourcen herunter, die sich geändert haben.

Über den Anwendungscache – oder AppCache – kann ein Entwickler angeben, welche Dateien der Browser zwischenspeichern und Offline-Nutzern zur Verfügung stellen soll. Ihre App wird korrekt geladen und funktioniert ordnungsgemäß, selbst wenn der Nutzer offline auf die Aktualisierungsschaltfläche klickt.

Die Cache-Manifest-Datei

Die Cache-Manifest-Datei ist eine einfache Textdatei, in der die Ressourcen aufgelistet sind, die der Browser für den Offline-Zugriff zwischenspeichern soll.

Auf eine Manifest-Datei verweisen

Zur Aktivierung des Anwendungscaches für eine App nehmen Sie das Manifestattribut in das html-Tag des Dokuments auf:

<html manifest="example.appcache">
  ...
</html>

In Ihrer Webanwendung sollte das manifest-Attribut auf jeder Seite enthalten sein, die im Cache gespeichert werden soll. Wenn eine Seite das manifest-Attribut nicht enthält, wird sie vom Browser nicht im Cache gespeichert, es sei denn, sie ist in der Manifest-Datei selbst explizit aufgeführt. Dies bedeutet, dass jede Seite mit einem manifest-Attribut, zu der der Nutzer navigiert, implizit dem Anwendungscache hinzugefügt wird. Daher muss nicht jede Seite im Manifest aufgeführt werden.

Das manifest-Attribut kann auf eine absolute URL oder einen relativen Pfad verweisen. Eine absolute URL muss sich jedoch am selben Ursprung befinden wie die Webanwendung. Eine Manifest-Datei kann zwar eine beliebige Dateiendung haben, allerdings muss der korrekte MIME-Typ für sie bereitgestellt werden.

<html manifest="http://www.example.com/example.mf">
  ...
</html>

Für eine Manifest-Datei muss der MIME-Typ text/cache-manifest bereitgestellt werden. Unter Umständen müssen Sie dem Webserver einen benutzerdefinierten Dateityp oder die .htaccess-Konfiguration hinzufügen.

Wenn Sie diesen MIME-Typ beispielsweise in Apache bereitstellen möchten, fügen Sie der Konfigurationsdatei folgende Zeile hinzu:

AddType text/cache-manifest .appcache

Alternativ fügen Sie in der Datei "app.yaml" in Google App Engine Folgendes hinzu:

- url: /mystaticdir/(.*\.appcache)
  static_files: mystaticdir/\1
  mime_type: text/cache-manifest
  upload: mystaticdir/(.*\.appcache)

Struktur einer Manifest-Datei

Ein einfaches Manifest könnte zum Beispiel so aussehen:

CACHE MANIFEST
index.html
stylesheet.css
images/logo.png
scripts/main.js

Bei diesem Beispiel werden vier Dateien auf der Seite gespeichert, von der diese Manifest-Datei angegeben wird.

Beachten Sie bitte folgende Hinweise:

  • Die Zeichenfolge CACHE MANIFEST ist die erste Zeile und obligatorisch.
  • Für Websites gilt eine Beschränkung auf 5 MB an zwischengespeicherten Daten. Wenn Sie jedoch eine App für den Chrome Web Store schreiben, können Sie diese Beschränkung durch unlimitedStorage aufheben.
  • Wenn die Manifest-Datei oder eine darin angegebene Ressource nicht heruntergeladen wird, schlägt die gesamte Cache-Aktualisierung fehl. Bei einem Ausfall greift der Browser weiterhin auf den alten Anwendungscache zu.

Im Folgenden sehen Sie ein komplexeres Beispiel:

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:
login.php
/myapi
http://api.twitter.com

# 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
*.html /offline.html

Zeilen, die mit einem Rautezeichen (#) beginnen, sind Kommentarzeilen. Sie können jedoch auch einem anderen Zweck dienen. Der Cache einer Anwendung wird nur bei einer Änderung der zugehörigen Manifest-Datei aktualisiert. Wenn Sie beispielsweise eine Bildressource bearbeiten oder eine JavaScript-Funktion ändern, werden diese Änderungen also nicht erneut im Cache gespeichert. Es ist erforderlich, die Manifest-Datei selbst zu ändern, damit der Browser die Information erhält, dass zwischengespeicherte Dateien aktualisiert werden sollen. Durch die Erstellung einer Kommentarzeile mit einer generierten Versionsnummer, einem Hash Ihrer Dateien oder einem Zeitstempel können Sie überprüfen, dass die Nutzer über die neueste Version Ihrer Software verfügen. Sie können den Cache auch programmatisch aktualisieren, sobald eine neue Version bereit ist. Weitere Informationen hierzu finden Sie im Abschnitt Cache aktualisieren.

Ein Manifest kann drei unterschiedliche Abschnitte aufweisen: CACHE, NETWORK und FALLBACK.

CACHE:
Dies ist der Standardabschnitt für Einträge. Unter diesem Header – oder direkt nach CACHE MANIFEST – aufgeführte Dateien werden nach dem ersten Herunterladen explizit im Cache gespeichert.
NETWORK:
Unter diesem Header aufgeführte Dateien sind Ressourcen, die in der weißen Liste aufgeführt sind und für die eine Verbindung zum Server erforderlich ist. Bei allen Anfragen an diese Ressourcen wird der Cache umgangen, selbst wenn der Nutzer offline ist. Es müssen Platzhalter verwendet werden.
FALLBACK:
Ein optionaler Abschnitt, in dem Fallback-Seiten angegeben sind für den Fall, dass auf eine Ressource nicht zugegriffen werden kann. Die erste URI ist die Ressource, die zweite das Fallback. Beide URIs müssen relativ sein und denselben Ursprung haben wie die Manifest-Datei. Es müssen Platzhalter verwendet werden.

Hinweis: Diese Abschnitte können in beliebiger Reihenfolge aufgeführt werden und jeder davon kann in einem einzelnen Manifest mehrmals erscheinen.

Durch das folgende Manifest wird eine "Catch-all"-Seite, "offline.html", definiert, die angezeigt wird, wenn der Nutzer versucht, offline auf den Stamm der Website zuzugreifen. Zudem wird darin deklariert, dass für alle anderen – beispielsweise für die auf einer Remote-Website befindlichen – Ressourcen eine Internetverbindung erforderlich ist.

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

Hinweis: Die HTML-Datei, die auf Ihre Manifest-Datei verweist, wird automatisch zwischengespeichert. Es ist nicht erforderlich, aber empfehlenswert, sie in Ihr Manifest aufzunehmen.

Hinweis: HTTP-Cache-Header und die Caching-Beschränkungen für über SSL bereitgestellte Seiten werden durch Cache-Manifeste außer Kraft gesetzt. Daher können über HTTPS bereitgestellte Seiten für eine Offline-Anzeige definiert werden.

Cache aktualisieren

Sobald eine Anwendung offline ist, bleibt sie im Cache gespeichert, bis eine der folgenden Bedingungen eintritt:

  1. Der Nutzer löscht den Datenspeicher seines Browsers für die Website.
  2. Die Manifest-Datei wird geändert. Beachten Sie, dass eine Aktualisierung der im Manifest aufgeführten Datei nicht dazu führt, dass diese Ressource erneut im Cache gespeichert wird. Die Manifest-Datei selbst muss ersetzt werden.
  3. Der App-Cache wird programmatisch aktualisiert.

Cache-Status

Das window.applicationCache-Objekt ist Ihr programmatischer Zugriff auf den App-Cache des Browsers. Anhand seiner status-Eigenschaft können Sie den aktuellen Status des Caches prüfen:

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;
};

Zur programmatischen Aktualisierung des Caches rufen Sie zunächst applicationCache.update() auf. Hierdurch wird versucht, den Cache des Nutzers zu aktualisieren, was eine Änderung der Manifest-Datei voraussetzt. Wenn schließlich applicationCache.status den Zustand UPDATEREADY aufweist, führt ein Aufruf von applicationCache.swapCache() dazu, dass der alte Cache zugunsten des neuen Caches ausgelagert wird.

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.
}

Hinweis: Werden update() und swapCache() auf diese Weise verwendet, so werden die aktualisierten Ressourcen nicht den Nutzern bereitgestellt. Durch diesen Ablauf erhält der Browser die Information, dass er eine Prüfung auf ein neues Manifest durchführen, den aktualisierten Inhalt herunterladen und den App-Cache neu füllen soll. Eine Seite muss daher zwei Mal neu geladen werden, damit Nutzern neue Inhalte bereitgestellt werden: einmal zum Einrichten eines neuen App-Caches und einmal zum Aktualisieren des Seiteninhalts.

Die gute Nachricht: Sie können diesen lästigen doppelten Ladevorgang vermeiden. Damit den Nutzern die neue Version Ihrer Website angezeigt wird, stellen Sie den Listener so ein, dass er beim Laden der Seite das updateready-Ereignis überwacht:

// 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.
      // Swap it in and reload the page to get the new hotness.
      window.applicationCache.swapCache();
      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);

AppCache-Ereignisse

Wie Sie vielleicht schon erwarten, werden zusätzliche Ereignisse zur Überwachung des Cache-Zustands verwendet. Der Browser löst beispielsweise Ereignisse für den Download-Fortschritt, das Aktualisieren des App-Caches und Fehlerbedingungen aus. Mit dem folgenden Snippet werden Ereignis-Listener für jede Art von Cache-Ereignis eingerichtet:

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);

Wenn die Manifest-Datei oder eine darin angegebene Ressource nicht heruntergeladen wird, schlägt die gesamte Aktualisierung fehl. Bei einem solchen Ausfall greift der Browser weiterhin auf den alten Anwendungscache zu.

Referenzen

Comments

0