Categorie
HTML5

Application cache

Una delle tante novità portate da HTML5 è la possibilità di memorizzare in locale un’applicazione Web. E’ vero che un sistema di caching locale delle pagine esiste già, questo è però gestito in maniera monocratica dai browsers, mentre adesso sarà lo sviluppatore stesso ad indicare quali risorse dovranno essere eventualmente memorizzate sul computer del visitatore. Saremo noi sviluppatori, quindi, ad avera la “palla in mano”. HTML5 ci offre gli strumenti per farlo.
Il meccanismo di funzionamento è molto semplice, si esegue il download delle risorse quando si è online per poterne poi usufruire quando siamo offline, e fino qui niente di nuovo.
La novità sta nella creazione di un file manifesto (cache manifest file) che non sarà altro che un elenco di URL di tutte le risorse (HTML, CSS, JavaScript ect..) che dovranno essere disponibili per la navigazione offline, forzandone quindi da parte del browser il salvataggio di una copia in locale.
Quello che dovremo fare sarà puntare al cache manifest file, che potrà trovarsi dove meglio crediamo all’interno del nostro server, attraverso l’attributo manifest del tag html:

<!DOCTYPE HTML>
<html manifest="cache.manifest">
<body>
...
</body>
</html>

L’attributo manifest può puntare a un URL assoluto oppure ad un percorso relativo, ma un URL assoluto deve essere sotto la stessa origine l’applicazione web.

Nota: Se la nostra applicazione è formata da più pagine, dobbiamo ricordarci che ogni pagina avrà bisogno di un attributo manifest che punti al file manifesto. Riassumendo, il browser non memorizzerà nella cache una pagina se questa non contiene l’attributo manifest (a meno che non è esplicitamente elencata nel file manifesto). Inoltre se non elenchiamo tutte le pagine (che vogliamo siano disponibili in locale) nel file manifesto, il browser non saprà che vi sono altre pagine che devono essere scaricate e memorizzati nella cache e non lo farà.

Master entries

Qualunque file HTML che include l’attributo manifest nel tag html è un master entry. Se il file non è incluso nel manifest file, la visita della pagina (cioè del file), causerà che questa sia aggiunta alla cache come master entry.

content type

Dobbiamo tenere presente che il cache manifest file dovrà essere servito dal server Web con il content type giusto, che in questo caso è text/cache-manifest. Se stiamo utilizzando Apache per esempio, dovremo mappare l’estensione con il content type attraverso AddType directive nel file .htaccess (che è posizionato nella root della nostra web directory):

AddType text/cache-manifest .manifest

Se utilizziate un altro server Web, consultarne allora la documentazione per capire come eseguire tale operazione.

Nota: Un file manifesto può avere qualsiasi estensione, l’importante e che sia servito con il corretto mime-type. Le specifiche adottano per esempio l’estensione .appcache

manifest file

Vediamo ora la struttura di un semplice manifest file:

CACHE MANIFEST
# version 1.0  05/01/2012

index.html
css/main.css
scripts/main.js
img/logo.png
  • Il manifest file deve sempre iniziare con la riga CACHE MANIFEST
  • La seconda riga inizia per # perchè è un commento. I commenti sono naturalmente opzionali tuttavia possono venirci in aiuto per forzare il refresh della cache. Difatti la cache verrà aggiornata soltanto se vi sono delle modifiche all’interno del manifesto, non se una risorsa viene modificata. Così potremmo trovarci nella situazione di modificare un file css o JavaScript senza che questo sia aggiornato nella cache. Modificando il file manifest, informeremo il browser che deve aggiornare i files presenti nella cache.
  • Se non riesce il download di una risorsa specificata nel manifesto, l’intero processo di aggiornamento della cache fallisce. Il browser continuerà ad usare la vecchia cache dell’applicazione (nel caso ve ne sia una).

Un utilizzo avanzato prevede la suddivisione del manifest file in tre sezioni: CAHE, NETWORK e FALLBACK.

  • CHACHE: Coincide con l’uso di default che abbiamo visto prima. I files elencati sotto questa intestazione (oppure direttamente sotto CACHE MANIFEST) saranno esplicitamente memorizzati nella cache.
  • NETWORK: I files di questa sezione sono considerati risorse white-list, che richiedono una connessione al server. Tutte le richieste a queste risorse baipasseranno la cache, anche se l’utente è offline. Possono essere utilizzati caratteri jolly.
  • FALLBACK: Questa sezione specifica delle pagine di ripiego se una risorsa non è accessibile. Il primo URI è la risorsa, il secondo rappresenta il fallback. Possono essere utilizzati caratteri jolly.

Vediamo ora un esempio:

CACHE MANIFEST
# version 2.0  05/01/2012

# Memorizzazione espicita nella cache
index.html
css/style.css

# risorsa di ripiego
FALLBACK:
/ /offline.html

# Risorse che richiedono di essere online. 
NETWORK:
/api

# risorse addizionali alla cache
CACHE:
img/logo.png
scripts/main.js

Da notare che nella sezione FALLBACK è stata aggiunta una risorsa che verrà visualizzata se il browser non trova la pagina nella cache. Il primo carattere (/) della riga è un URL pattern che matcherà qualsiasi pagina nel sito, non soltanto la home come verrebbe da pensare.
Nella sezione NETWORK invece ci assicuriamo che le richieste per caricare le risorse contenute nel sottoalbero /api/ non tentino di accedere alla cache.

Nota: Le risorse possono risiedere in più sezioni contemporaneamente. Per esempio, una voce può essere sia una di quelle esplicite che una voce di ripiego.

Formato dati

Il formato per le linee di dati varia da sezione a sezione. Nella sezione esplicita (cache), ogni riga è un URI od IRI valido (i caratteri jolly sono ammessi in questa sezione). Uno spazio bianco è ammesso prima e dopo l’URI od IRI su ogni linea. Nella sezione Fallback ogni riga è un URI od IRI valido ad una risorsa, seguito da una risorsa di fallback. Nella sezione di nertwork, ogni riga è un URI od IRI valido (il carattere jolly * è consentito in questa sezione).

Nota: Gli URI relativi sono relativi alla URI del manifesto, non alla URI del documento con riferimento al manifesto.

Eventi

Quando un browser visita una pagina che punta ad un file manifest, vengono attivati una sequenza più o meno lunga di eventi sull’oggetto window.applicationCache. Tutti gli eventi elencati qui sono licenziati su tale oggetto.

Nome evento Descrizione
checking Appena il browser nota una attributo manifest sull’elemento html licenzia questo evento, che cercherà di scaricare il manifesto per la prima volta oppure controllerà per un aggiornamento nel caso il manifesto sia già stato scaricato. Questo è sempre il primo evento della sequenza.
noupdate Evento licenziato se il manifesto non è cambiato. Ultimo evento nella sequenza.
downloading Questo evento viene licenziato nel caso il manifesto sia stato scaricato per la prima volta oppure sia stato modificato. L’evento inizierà rispettivamente a scaricare o riscaricare ogni singola risorsa elencata nel manifesto.
progress Mentre esegue il download, il browser licenzia periodicamente l’evento progress, che contiene info su quanti files sono stati scaricati e quanti sono ancora in coda di scaricamento.
cached Evento attivato quando tutte le risorse elencate nel manifest file sono state scaricate e quindi saranno disponibili per la navigazione offline. Ultimo evento nelle sequenza.
updateready In caso di aggiornamento del manifesto, quando tutte le risorse saranno state riscaricate, il browser licenzierà questo evento che indica che la nuova cache è disponibile. Per forzare la nuova versione senza costringere l’utente a ricaricare la pagine è possibile eseguire una chiamata al metodo swapCache(). Ultimo evento nelle sequenza.
error Viene licenziato nei seguenti casi:

  1. Il manifesto ritorna un errore HTTP 404 (Page Not Found) o 410 (Permanently Gone).
  2. Il manifesto non è cambiato ma la pagina che punta ad esso non è stata scaricata correttamente.
  3. Il browser non è riuscito a scaricare una delle risorse elencate nel cache manifest.
  4. Il manifesto è cambiato, mentre l’aggiornamento era in esecuzione.

Stato della cache

Ogni applicazione ha uno stato della cache, che indica la condizione attuale della cache, possiamo monitorarlo attraverso la proprietà status dell’oggetto window.applicationCache:

  • UNCACHED
    Un valore speciale che indica che l’oggetto cache non è completamente inizializzato.
  • IDLE
    La cache non è attualmente in corso di aggiornamento.
  • CHECKING
    Il manifesto è in scaricamento e si sta controllando per gli aggiornamenti.
  • DOWNLOADING
    Le risorse sono in fase di download a causa di un cambiamento del manifesto.
  • UPDATEREADY
    E’ disponibile una nuova versione della cache. Come detto, c’è un evento corrispondente updateready, che è licenziato quando un nuovo aggiornamento è stato scaricato ma non ancora attivato utilizzando il metodo swapCache().
  • OBSOLETE
    La cache è ormai obsoleta.
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 'STATO SCONOSCIUTO';
    break;
};
Nota: La cache può diventare obsoleta. Nel caso in cui il manifesto sia stato rimosso dal server, il browser rimuoverà tutta la cache utilizzata dall’applicazione, quindi licenzierà un evento obsoleted sull’oggetto cache. Poi lo stato della cache sarà spostato su OBSOLETE.

Il processo di aggiornamento

Ora che abbiamo in mano tutte le informazioni, ricapitoliamo come si sviluppa in realtà il processo:

  1. Quando il browser visita un documento che include un attributo manifest e se non esiste ancora la cache dell’applicazione, caricherà il documento e tutte le voci elencate nel file manifest, creando la prima versione della cache dell’applicazione.
  2. Le visite successive a tale documento faranno scattare il browser a caricare il documento, e le altre risorse specificate nel file manifesto, dalla cache e non dal server, in aggiunta il browser invierà un evento checking per l’oggetto window.applicationCache, poi preleverà il file manifesto, seguendo le appropriate regole di caching HTTP.
  3. Se la copia del manifesto nella cache è aggiornata, l’evento noupdate viene inviato all’applicationCache, e il processo di aggiornamento è completo. (È per questo che se si cambia una o più risorse sul server, è necessario modificare anche il file manifesto in modo che il browser sa che deve prendere tutte le risorse ancora una volta).
    Se il file manifesto è cambiato, tutti i files nel manifesto, vengono recuperati in una cache temporanea. Per ogni file recuperato in questa cache temporanea, sarà licenziato un evento progress sull’oggetto applicationCache.
    In caso di errori, un evento di error sarà licenziato, e la fermerà l’aggiornamento.
  4. Una volta che tutti i files sono stati recuperati correttamente, vengono spostati nella cache reale ed un evento cached viene licenziato sull’oggetto applicationCache. Poiché il documento è già stato caricato nella cache del browser, il documento aggiornato non sarà reso fino a quando il documento non sarà ricaricato (manualmente o programmaticamente).

Supporto dei Browsers

[browserSupport ie=10.0+ firefox=3.5+ chrome=4.0+ safari=4.0+ opera=10.6+]

Conclusioni

A mio avviso, ad oggi visto la mancanza di supporto da parte di IE (disponibile solo dalla versione 10) la tecnologia può trovare ancora delle restrizioni sull’impiego effettivo, tuttavia Google ha già provveduto a dismettere il progetto Gears per dare pieno supporto ad HTML5, e questo è un segnale.
Inoltre Hotmail sembra intenzionata a risolvere il gap nei confronti di GMAIL sull’archiviazione offline supportando l’application cache. Non mi stupirei se tra qualche tempo i client di posta saranno definitivamente archiviati e sostituiti dalle applicazioni online (consultabili anche offline :)).
Inoltre la feature oltre ad essere ideale per i dispositivi mobili (visto il tipo di connessione) e per le applicazioni progettate per funzionare in uno stato non in linea potrebbe migliorare sensibilmente le prestazioni delle applicazioni web online, fruttandola per il caching di risorse statiche.

Risorse

www.whatwg.org/specs/web-apps/current-work/multipage/offline.html

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.