¿Qué es Application Cache?
Esta especificación está
pensada para escenarios donde podemos experimentar situaciones
en las que no disponemos de conectividad,
como en un avión, zonas con poca cobertura, desconexiones intermitentes,
etcétera. Hasta ahora con el modo de caché habitual no éramos capaces de
obtener recursos a los que no hubiéramos accedido previamente, ni podíamos
indicar a qué páginas era posible navegar aún cuando no disponíamos de acceso
al servidor, por falta de Internet o porque el mismo no estuviera disponible en
ese momento. Pero no sólo los escenarios relacionados con la conectividad son
los candidatos de disfrutar de esta API, sino que también nos
permite mejorar rendimiento del servidor reduciendo las peticiones de recursos
en usuarios recurrentes, manteniendo los más estáticos cacheados en el
navegador de forma explícita.
Esta característica está
siendo muy utilizada en diferentes escenarios como juegos (como la aplicación de Angry Birds de Chrome Web Store), aplicaciones offline
de acceso al correo electrónico, clientes
web de música por streaming como Deezer y todas aquellas que puedan trabajar en local
y sean capaces de sincronizar su contenido más tarde, o necesiten reducir el
flujo de peticiones.
¿Cómo funciona?
Para poder trabajar con App
Cache lo primero que debemos conocer es el archivo llamado cache
manifest. Se trata de un archivo de
texto plano con la siguiente estructura:
CACHE MANIFEST
#version 5.9
CACHE:
#This section list all resources that should be
downloaded and store locally
#HTML files
index.html
#JavaScript files
/Scripts/appCache.js
/Content/images/glyphicons-halflings.png
/Scripts/bootstrap.min.js
/Scripts/jquery-1.9.1.min.js
#CSS files
/Content/bootstrap.min.css
NETWORK:
#This section list all URLs that may be loaded over
Internet.
online.html
FALLBACK:
#Lists replacements for network URLs to be used
when the browser is offline or the remote server is unavailable
/home.html /offline.html
/Content/images/glyphicons-halflings-white.png
/Content/offline.png
En primer lugar, todo
manifiesto debe comenzar con CACHE MANIFEST en la primera línea del
archivo, de lo contrario podemos encontrar problemas cuando se intenta procesar
por el navegador.
También es importante tener
cuidado con los códigos de control que inserta Visual Studio al crear este
fichero dentro de una solución, por lo que recomiendo guardar el mismo
como Unicode (UTF-8 without signature) – Codepage 65001 a través de File
–> Advanced Save Options.
Todas aquellas líneas que
comiencen con una almohadilla (#) se tratan de comentarios. A continuación
revisamos las siguientes secciones del manifiesto:
CACHE
Listado de todos aquellos recursos que deben ser descargados y
almacenados localmente.
NETWORK
Lista de todas las URL que necesitan acceso al servidor remoto/Internet.
Es posible utilizar el asterisco para indicar que cualquier recurso que no esté
listado en el apartado CACHE necesita acceso a la red para acceder a él. Es
posible hacer uso de URLs relativasy absolutas.
FALLBACK
En el caso de no tener acceso al servidor remoto se pueden especificar
qué recursos deben responder por aquellos que no pueden ser recuperados. Los
mismos pueden ser de cualquier tipo (una página HTML, una imágen, código
JavaScript, etcétera). El primer parámetro es el recurso al que nos gustaría
acceder y el segundo el que tomará su lugar cuando existan problemas de
conectividad.
Para indicar que un sitio
tiene un manifiesto relacionado, basta con asociarlo en la etiqueta html de la página:
<!DOCTYPE html>
<html manifest="manifest.appcache">
<head>
El mismo puede tener el
nombre y extensión que se prefiera, pero con convención se sugiere *.appcache. Como MIME type del mismo es recomendable
servir text/cache-manifest. Si trabajamos con aplicaciones .NET podemos
establecerlo a nivel del archivo web.config de la siguiente forma:
<?xml version="1.0"?>
<!--
For more
information on how to configure your ASP.NET application, please visit
http://go.microsoft.com/fwlink/?LinkId=169433
-->
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5" />
</system.web>
<system.webServer>
<staticContent>
<mimeMap fileExtension=".appcache" mimeType="text/cache-manifest"/>
</staticContent>
</system.webServer>
</configuration>
Ciclo de vida de Application Cache
Una vez que la página asociada al manifiesto haya
cargado, lo primero que el
navegador comprobará es si tiene la versión más reciente del manifiesto para
ese sitio. De no ser así descargará del servidor la última
versión. Una vez obtenida
comenzará a descargar todos los recursos nombrados en el apartado CACHE y
aquellos que podrían ser utilizados como FALLBACK, en el caso de que no
pudiéramos alcanzar el servidor de destino. A partir de este momento se
trabajará con los recursos cacheados y no volverán a descargarse hasta que el manifiesto vuelva a sufrir una
nueva actualización o limpiemos los datos temporales del navegador.
Si quisiéramos comprobar su efectividad, basta con desconectar el dispositivo
de Internet e intentar navegar a aquellas páginas y recursos que fueron
nombrados en el manifiesto. Del mismo modo, si intentáramos acceder a aquellos
recursos que poseen un fallback, el navegador nos desviaría directamente a
aquellas URL indicadas como segundo parámetro.
Eventos
En las versiones más recientes de Chrome (En el
momento del post Chrome 26) es posible ver los eventos ocurridos a través de la
consola de la herramienta de desarrollo:
No obstante, es posible añadir manejadores a cada uno
de ellos con el siguiente código JavaScript:
|
Lo primero que comprobamos en nuestro código es si
Application Cache está soportado por nuestro navegador (las últimas versiones
de los navegadores más populares ya lo implementan). Para tener una visión más
completa de la disponibilidad de esta característica podemos consultar esta tabla.
En cuanto a los eventos tenemos los siguientes:
checking
Se lanza cuando el navegador está comprobando la
última versión del manifiesto alojada en el servidor remoto.
downloading
Indica que el manifiesto ha sido descargado y comienza
la obtención de los recursos.
noupdate
Indica que tenemos la última versión del manifiesto y
no es necesario descargar ningún recurso.
obsolete
La versión del servidor está obsoleta.
progress
Se lanza por cada uno de los recursos incluídos en la
sección CACHE
error
Como su propio nombre indica, se trata del evento
reservado para los errores durante la obtención de los recursos indicados en el
manifiesto.
updateready
Nos permite conocer cuándo todos los recursos han sido
actualizados con la nueva versión. En este ejemplo, además de mostrar el texto
correspondiente, hacemos una comprobación al terminar el switch donde
verificamos si hemos llegado a este punto y forzamos el cambio de cache a los
nuevos elementos a través de la función swapCache(). Si bien esta
función nos ahorra una recarga en el sitio, swapCache no nos permite servir los
recursos actualizados de manera automática, por lo que debemos preguntar al
usuario si podemos refrescar la página para aplicar los nuevos cambios.
cached
Los recursos han sido descargados y la aplicación ha
sido cacheada. Este evento sólo ocurre la primera vez que se cachea el
contenido. En las siguientes descargas será updateready el que se lance.
También es posible solicitar la actualización de la
cache a través de script (sin tener que refrescar la página) utilizando window.applicationCache.update(),
aunque será necesario igualmente el swap de la caché y el refresco de la página
para poder aplicar los últimos cambios. Suele utilizarse cuando el usuario ha
estado trabajando durante mucho tiempo en el sitio sin tener que refrescar la
página y recuperar así el nuevo manifiesto durante una recarga.
En este ejemplo la misma función controla todos los
eventos posibles y, a través de un switch, muestra además el estado que refleja
cada uno de ellos donde curiosamente no tiene por qué coincidir con el nombre
del evento. Podemos verlo en la siguiente imagen:
Eventos Online y Offline
Por último, aunque no pertenezca a la API de App
Cache, me gustaría mostrar la forma de conocer cuándo una aplicación no dispone
de acceso a Internet… ¡Efectivamente! Existe otra API para ello En este caso debemos hablar de los eventos
online y offline pertenecientes al objeto window. A través de la propiedad
navigator.onLine podemos conocer cuál es nuestro estado actual e
incluso podemos manejar los eventos online y offline de la siguiente manera:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
Como podemos ver en el ejemplo, hemos encapsulado el
valor de [window.]navigator.onLine en la función isOnline con el objetivo de
comprobar dentro de internetStatus cuál es su valor y asociar una clase y un
texto a una etiqueta con id “internet” en nuestra página. Además asociamos esta
función a los eventos online y offline de window para que, cada vez que
ocurran, se vuelta a comprobar el estado de nuestro acceso a Internet. Por
último se llama a internetStatus una primera vez al cargar la página para
conocer en qué estado nos encontramos inicialmente.
Podéis encontrar más información y demos en la
página Appcache Facts.
Existe una página llamada Cache Manifest Validator que nos permite comprobar si hemos creado
nuestro manifiesto correctamente. De hecho, también disponemos de una extensión
para Chrome que realiza la
misma función.
DEMOSTRACIÓN
En nuestro Panel de proyecto crearemos tres archivos .html como lo hemos
hecho en los ejemplos anteriores, de nombres insex.html, about.html y
contact.html como se muestra a continuación
En la página Index.html su código HTML será el siguiente:
En la página About.html su código HTML será el siguiente:
En la página Contact.html su código HTML será el siguiente:
Ahora Procederemos a crear un archivo de texto para nuestro proyecto. En el
espacio de nombre del proyecto damos click derecho y seleccionamos Add à New Items
En la siguiente ventana seleccionamos en la parte Izquierda la opción de
“General”, Luego seleccionamos el archivo de tipo “TextFile” y en el nombre
colocamos “manifest.appcache.text” y le damos click al botón Add.
Allí escribimos lo siguiente:
Y en la etiqueta <HTML> al inicio de nuestro código en las páginas
index.html, about.html y contact.html colocamos el manifiesto haciendo
referencia a nuestro archivo de texto
Establecemos el archivo Index.html como nuestra página principal
Y la desplegamos (Para este ejemplo uso Google Chrome).
Procedemos a abrir el panel para ver la consola
Fíjese que ya nos muestra información en la caché del navegador
Si
le damos click a Network
Y
le damos click a las opciones de About y Contact de nuestra página fijesé que
se almacena en el caché lo correspondiente a las páginas web