Introduzione
È sempre più importante che le applicazioni web siano accessibili offline. Sì, tutti i browser possono memorizzare nella cache pagine e risorse per lunghi periodi se gli viene chiesto, ma il browser può rimuovere singoli elementi dalla cache in qualsiasi momento per fare spazio ad altri elementi. 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.
Di conseguenza, non è necessario elencare ogni pagina nel 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 manifest è un file separato a cui fai riferimento tramite l'attributo manifest dell'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.
Ecco un paio di aspetti da tenere presente:
- 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 limitazione. - Se il manifest stesso restituisce un codice 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 "#" sono righe di commento, ma possono avere anche un altro scopo. La cache di un'applicazione viene aggiornata solo quando il file manifest cambia. Ad esempio, se modifichi una risorsa immagine o una funzione JavaScript, queste modifiche non verranno memorizzate nuovamente nella cache. Devi modificare il file manifest stesso per indicare 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 subito dopo
CACHE MANIFEST
) vengono memorizzati nella cache in modo esplicito dopo essere stati scaricati per la prima volta.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. Qui puoi inserire URL specifici nella lista consentita oppure semplicemente "", che consente tutti gli URL. La maggior parte dei siti ha bisogno di "".
FALLBACK:
- Una 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 provenire dalla stessa origine del file manifest. Puoi acquisire URL specifici, ma anche prefissi URL. "images/large/" acquisirà gli errori da URL come "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) richiedono 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
Una volta offline, un'applicazione rimane in cache finché non si verifica uno dei seguenti casi:
- 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 attuale 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 applicationCache.status
è nello stato UPDATEREADY
,
la chiamata a applicationCache.swapCache()
sostituirà la vecchia cache con la 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 aspetti quali l'avanzamento del download, l'aggiornamento della cache dell'app e le condizioni di errore. Lo snippet seguente configura gli ascoltatori di eventi per ogni tipo di evento della 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 va a buon fine. In caso di un tale errore, il browser continuerà a utilizzare la vecchia cache dell'applicazione.
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.