Introduzione
È sempre più importante che le applicazioni web siano accessibili offline. Sì, tutti i browser, se richiesto, possono memorizzare nella cache pagine e risorse per lunghi periodi, ma il browser può estrarre dalla cache singoli elementi in qualsiasi momento per fare spazio ad altre cose. HTML5 risolve alcuni dei problemi dell'utilizzo offline con l'interfaccia ApplicationCache. L'utilizzo dell'interfaccia della cache offre alla tua applicazione tre vantaggi:
- Navigazione offline: gli utenti possono navigare nel tuo sito completo quando sono offline
- Velocità: le risorse vengono caricate direttamente dal disco, senza passare dalla rete.
- Resilienza: se il tuo sito non è disponibile per "manutenzione" (ad esempio se qualcuno rompe accidentalmente tutto), gli utenti avranno un'esperienza offline
La cache dell'applicazione (o AppCache) consente a uno sviluppatore di specificare quali file deve memorizzare nella cache il browser e rendere disponibili per gli utenti offline. L'app verrà caricata e funzionerà correttamente, anche se l'utente preme il pulsante di aggiornamento mentre è offline.
Il file manifest della cache
Il file manifest della cache è un semplice file di testo che elenca le risorse che il browser deve memorizzare nella cache per l'accesso offline.
Fare riferimento a un file manifest
Per attivare la cache dell'applicazione per un'app, includi l'attributo manifest nel tag html
del documento:
<html manifest="example.appcache">
...
</html>
L'attributo manifest
deve essere incluso in ogni pagina della tua applicazione web
che vuoi memorizzare nella cache. Il browser non memorizza nella cache una pagina se non contiene
l'attributo manifest
(a meno che non sia elencato esplicitamente
nel file manifest stesso. Ciò significa che qualsiasi pagina visitata dall'utente che include un manifest
verrà aggiunta implicitamente alla cache dell'applicazione.
Pertanto, non è necessario elencare ogni pagina del file manifest. Se una pagina rimanda a un manifest, non è possibile impedire la memorizzazione nella cache di questa pagina.
Puoi vedere gli URL controllati dalla cache dell'applicazione visitando about://://appcache-internals/ in Chrome. Da qui puoi svuotare le cache e visualizzare le voci. In Firefox sono disponibili strumenti per sviluppatori simili.
L'attributo manifest
può puntare a un URL assoluto o a un percorso relativo, ma un URL assoluto deve trovarsi nella stessa origine dell'applicazione web.
Un file manifest può avere qualsiasi estensione, ma deve essere pubblicato con il tipo MIME corretto (vedi di seguito).
<html manifest="http://www.example.com/example.mf">
...
</html>
Un file manifest deve essere pubblicato con il tipo MIME text/cache-manifest
.
Potresti dover aggiungere un tipo di file personalizzato al server web o alla configurazione di .htaccess
.
Ad esempio, per pubblicare questo tipo MIME in Apache, aggiungi questa riga al file di configurazione:
AddType text/cache-manifest .appcache
In alternativa, nel file app.yaml in Google App Engine:
- url: /mystaticdir/(.*\.appcache)
static_files: mystaticdir/\1
mime_type: text/cache-manifest
upload: mystaticdir/(.*\.appcache)
Questo requisito è stato rimosso dalla specifica qualche tempo fa e non è più richiesto dalle versioni più recenti di Chrome, Safari e Firefox, ma il tipo MIME è necessario per il funzionamento nei browser meno recenti e in IE11.
Struttura di un file manifest
Il file manifest è un file separato al quale puoi collegarti tramite l'attributo manifest nell'elemento html. Un manifest semplice ha il seguente aspetto:
CACHE MANIFEST
index.html
stylesheet.css
images/logo.png
scripts/main.js
http://cdn.example.com/scripts/main.js
In questo esempio verranno memorizzati nella cache quattro file nella pagina che specifica questo file manifest.
Tieni presente alcune cose:
- La stringa
CACHE MANIFEST
è la prima riga ed è obbligatoria. - I file possono provenire da un altro dominio
- Alcuni browser impongono limitazioni alla quantità di quota di spazio di archiviazione disponibile per la tua app. Ad esempio, in Chrome AppCache utilizza un pool condiviso di spazio di archiviazione TEMPORANEO che altre API offline possono condividere. Se stai scrivendo un'app per il Chrome Web Store, l'utilizzo di
unlimitedStorage
rimuove questa restrizione. - Se il manifest stesso restituisce un errore 404 o 410, la cache viene eliminata.
- Se il download del manifest o di una risorsa specificata al suo interno non va a buon fine, l'intera procedura di aggiornamento della cache non va a buon fine. In caso di errore, il browser continuerà a utilizzare la vecchia cache dell'applicazione.
Vediamo un esempio più complesso:
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
Le righe che iniziano con un "#" sono righe di commento, ma possono servire anche per un altro scopo. La cache di un'applicazione viene aggiornata solo quando il file manifest viene modificato. Ad esempio, se modifichi una risorsa immagine o una funzione JavaScript, queste modifiche non verranno memorizzate nuovamente nella cache. Devi modificare il file manifest per comunicare al browser di aggiornare i file memorizzati nella cache.
Evita di utilizzare un timestamp in continuo aggiornamento o una stringa casuale per forzare gli aggiornamenti ogni volta. Il manifest viene controllato due volte durante un aggiornamento, una all'inizio e una dopo l'aggiornamento di tutti i file memorizzati nella cache. Se il manifest è cambiato durante l'aggiornamento, è possibile che il browser abbia recuperato alcuni file da una versione e altri da un'altra, quindi non applica la cache e riprova in un secondo momento.
Sebbene la cache venga aggiornata, il browser non utilizzerà questi file finché la pagina non viene aggiornata, perché gli aggiornamenti vengono eseguiti dopo il caricamento della pagina dalla versione corrente della cache.
Un manifest può avere tre sezioni distinte: CACHE
, NETWORK
e FALLBACK
.
CACHE:
- Questa è la sezione predefinita per le voci. I file elencati sotto questa intestazione (o immediatamente dopo
CACHE MANIFEST
) verranno memorizzati nella cache esplicitamente dopo il primo download.NETWORK:
- I file elencati in questa sezione possono provenire dalla rete se non sono nella cache, altrimenti la rete non viene utilizzata, anche se l'utente è online. Puoi inserire URL specifici nella lista consentita qui o semplicemente "", che consente tutti gli URL. La maggior parte dei siti richiede "".
FALLBACK:
- Sezione facoltativa che specifica le pagine di riserva se una risorsa non è accessibile. Il primo URI è la risorsa, mentre il secondo è il valore alternativo utilizzato se la richiesta di rete non va a buon fine o genera errori. Entrambi gli URI devono avere la stessa origine del file manifest. Puoi acquisire URL specifici, ma anche prefissi URL. "images/large/" acquisirà gli errori da URL quali "images/large/whatever/img.jpg".
Il seguente manifest definisce una pagina "generica" (offline.html) che verrà visualizzata quando l'utente tenterà di accedere alla radice del sito in modalità offline. Dichiara inoltre che tutte le altre risorse (ad es. quelle su un sito remoto) require una connessione a 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
Aggiornamento della cache in corso...
Quando un'applicazione è offline, rimane memorizzata nella cache fino a quando si verifica una delle seguenti condizioni:
- L'utente cancella lo spazio di archiviazione dei dati del browser per il tuo sito.
- Il file manifest è modificato. Nota: l'aggiornamento di un file elencato nel manifest non significa che il browser ricaricherà la risorsa. Il file manifest stesso deve essere modificato.
Stato della cache
L'oggetto window.applicationCache
è il tuo accesso programmatico alla cache dell'app del browser.
La sua proprietà status
è utile per controllare lo stato corrente della 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;
};
Per verificare tramite programmazione la presenza di aggiornamenti al manifest, chiama prima applicationCache.update()
.
Verrà tentato di aggiornare la cache dell'utente (il che richiede la modifica del file manifest).
Infine, quando il applicationCache.status
è nello stato UPDATEREADY
,
chiamando applicationCache.swapCache()
la vecchia cache verrà sostituita con quella nuova.
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.
}
La buona notizia è che puoi automatizzare questa operazione. Per aggiornare gli utenti alla
versione più recente del tuo sito, imposta un ascoltatore per monitorare
l'evento updateready
al caricamento della pagina:
// 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);
Eventi AppCache
Come previsto, vengono esposti eventi aggiuntivi per monitorare lo stato della cache. Il browser attiva eventi per, ad esempio, l'avanzamento del download, l'aggiornamento della cache dell'app e le condizioni di errore. Lo snippet seguente imposta i listener di eventi per ciascun tipo di evento 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);
Se non è possibile scaricare il file manifest o una risorsa specificata al suo interno, l'intero aggiornamento non andrà a buon fine. In caso di errore, il browser continuerà a utilizzare la cache dell'applicazione precedente.
Riferimenti
- Specifica dell'API ApplicationCache
- Application Cache is a douchebag (La cache dell'applicazione è una sega) - che illustra i problemi e le insidie di AppCache.