Aggressive Client Caching mit Hilfe von HTML 5 Manifesten

Die Anforderung von Webseiten in puncto Performance und Datenmengen steigen immer weiter an. Dies führt dazu, dass das Caching für Webseiten einen immer wichtigeren Standpunkt einnimmt und in der Priorität steigt.

Bislang war es üblich, dass statische Ressourcen – also Javascript- und CSS-Dateien – über ein Server-gesteuertes Caching auf dem Client zwischengespeichert werden.

Im Rahmen von HTML5 und modernen, Client-orientierten Webanwendungen gibt es nun aber eine weitere Möglichkeit: Offline Apps.

Offline Apps sind prinzipiell auch nur Webseiten, die im Internet verfügbar sind; über eine sogenannte Manifest-Datei können wir aber theoretisch alle statischen Ressourcen und HTML Dateien im Browser des Anwenders ablegen.

HTML5 Application Cache

Im Rahmen von HTML wurde der sogenannte Application Cache eingeführt. Hier können Webseiten völlig verschiedene Daten im Browser ablegen dauerhaft ablegen und eben so auch Offline verfügbar machen.

Dieses Verhalten können wir für ein sogenannte Aggressive Client Caching ausnutzen

Manifest

Um den Browser mitteilen zu können, was er sich speichern soll, muss eine sogenannte Manifest-Datei angelegt und im <html>-Tag bekannt gemacht werden werden.

Der Browser lädt initial das Manifest und alle darin definierten Elemente. Elemente, die dauerhaft gespeichert werden sollen, werden im Bereich CACHE definiert. Dazu gehören zum Beispiel CSS- oder Javascript-Dateien, die sich selten ändern. Im Bereich NETWORK muss alles definiert werden, was Online verfügbar sein bzw. nicht zwischengespeichert werden soll. Das sind z.B. Bewegungsdaten, eine externe API oder auch ganz einfach PHP- oder Server-generierte HTML-Dateien.

Wenn der Browser ein Mal die Daten geladen hat, greift er solange nicht mehr auf die Elemente unterhalb von CACHE zu, bis sich das Manifest geändert hat. Dabei beachtet der Browser nicht das Datum der Manifest-Datei, sondern den Inhalt. Es ist also absolut notwendig, dass ihr den Inhalt der Manifest-Datei aktualisiert, sobald ihr eine darin definierte, zwischengespeicheres Element ändert. Ganz einfach: über ein Zeitstempel im Manifest.

Beachtet, dass ihr unter dem Punkt Network ein Sternchen (*) als letzten Eintrag setzt, sodass Dateien, die nicht im Manifest hinterlegt sind, trotzdem versucht werden über den Server zu laden.

Das Manifest

CACHE MANIFEST
# Aktualisiert diese Zeitstempel, sobald sich eine Datei unter CACHE ändert
# 2015-02-11
 
# Alle Elemente, die unter diesem CACHE definiert werden, werden im Browser-Application Cache
# abgelegt. Es erfolgt kein weiterer Zugriff auf diese Datei auf dem Server, solange sich
# dieses Manifest nicht ändert!
CACHE:
/favicon.ico
index.html
stylesheet.css
/CSS/Styles.css
/Content/CSS/*
/Content/images/*
 
# Unter dem Punkt NETWORK definiert ihr Elemente,
# die ONLINE verfügbar sein müssen; zB APIs oder dynamische HTML-Dateien
NETWORK:
user.php
/api
http://api.twitter.com
# GANZ WICHTIG!!
*
# Das Sternchen bewirkt, dass alle Dateien, die hier nicht definiert sind, versucht werde
# vom Server zu laden. Ansonsten können nicht-definierte Dateien NICHT verwendet werden!!
 
# Anschließend noch die Definition von Fallbacks, also wenn auf Online-Ressourcen
# nicht zugegriffen werden können. Hier wird nun eine 'user-offline-html' 
# abgezeigt, sobald user.php nicht verfügbar ist
FALLBACK:
user.php user-offline.html

Nach einer Manifest-Aktualisierung

Nachdem die Manifest-Datei aktualisiert wurde, wird der Browser beim nächsten Besuch die Inhalte neu laden. Diese sind jedoch nicht sofort verfügbar, sondern erst nach einem erneuten Laden der Seite!

Über JavaScript (window.applicationCache) kann der Status der Aktualisierung (Available, Downloading, Ready…) abgefragt werden, sodass der Anwender benachrichtigt werden kann.

Das Auslösen der Aktualisierung erfolgt aber nicht nur durch eine aktuellere Manifest-Datei; sie wird auch erfolgen, wenn der Nutzer den Cache manuell löscht oder wenn die Aktualisierung programmatisch angestoßen wird.

function getCacheState() {
    switch (window.applicationCache) {
        case 0:
            return 'UNCACHED';
 
        case 1:
            return 'IDLE';
 
        case 2:
            return 'CHECKING';
 
        case 3:
            return 'DOWNLOADING';
 
        case 4:
            return 'UPDATE READY';
 
        case 5:
            return 'OBSOLETE';
 
        default:
            return 'UKNOWN';
    }
}

Fazit

Wir können mit einer Manifest-Datei den Traffic an den Client auf ein Minimum reduzieren, da wir die Ressourcen nur noch laden, wenn sie sich wirklich geändert haben.

Die Umsetzung erfordert aber einen zuverlässigen Build-Prozess, sodass die Manifest-Datei automatisiert aktualisiert und die Änderung vom Client geladen werden kann.

Bei einer gut durchdachten Webseite kann es den Traffic massiv senken; insbesondere mit der Nutzung von Single-Page-Applications (SPA, zB mit Hilfe von Angular), bei denen wir mit statischen HTML-Dateien arbeiten und die Business-Daten nur noch über APIs laden.