¿Cómo puedo hacer que mi aplicación web o móvil funcione offline?

Ideas generales

En este mundo que vivimos la conectividad y el alcance que tenemos con la web a veces olvidamos nuestra dependencia sobre los proveedores de servicios. En nuestro caso venezolano sufrimos el constante embate de los elementos y su efecto en las telecomunicaciones de la nación, o al menos es lo que te dicen cuando llamas a atención al cliente. Obviando este tema, para nosotros los desarrolladores tenemos un reto, a nivel mundial se habla de alcanzar o darle acceso a aquellos en zonas rurales o remotas pero también se habla de garantizar el uso de las herramientas que usamos y ser sinceros con nuestros usuarios con mensajes “Epa, estas desconectado, estas usando la versión offline, cuando tu conexión vuelva sincronizamos tus cambios” algo parecido a lo que hace Evernote cuando escribes, creas o cambias una nota.

Llegamos al punto donde nos preguntamos, ¿Qué podemos hacer al respecto? Me hicieron esta pregunta hace algunos días y yo también me la había planteado pero no estaba seguro cual era la ruta a seguir. Resolví investigar cuales son las alternativas y encontré una serie de ideas al respecto.

Inicialmente el referente que tenía era esa idea de sincronización que presentan aplicaciones como Evernote o Dropbox donde trabajas localmente y cuando en algún momento tengas conexión a Internet tus cambios son actualizados con ese repositorio central que está en la nube. Esto me sonó muy similar a como funciona Git donde descentralizando la posesión de los archivos y teniendo copias del repositorio se designa un repositorio central que mantiene una línea común entre todos. Por ende el problema que le veía era como representar esa capacidad de Git y su almacenamiento de manera local.

Enfoque de Sincronización y Snapshots

Desde el punto de vista de las aplicaciones móviles nativas véase iOS y Android encontré más lógico que debía haber algo parecido a una réplica local de la aplicación y su estructura de datos, un snapshot de los datos a usar. Esto requiere indicar también como se puede hacer para diferenciar el momento en el tiempo que representa la copia “móvil” que tiene la aplicación contra el repositorio central. También hay que tomar en cuenta detalles técnicos como:

  • Sincronización de id’s durante los procesos de replicación y sincronización.
  • Resolución de conflicto entre las operaciones desarrolladas a nivel Web y la aplicación móvil

En cualquier caso se hace necesario que en este aspecto se trabaje sobre un enfoque bien definido, suena lógico pero llegar al enfoque requiere meditar sobre el asunto, diseñar la arquitectura y los planes de acción al sincronizar, en este y este enlace (están en inglés) podemos ver algunos enfoques sobre cómo manejar este aspecto de sincronización. Finalmente y como último aporte a esta sección de este post, hay una publicación de la Universidad de Vanderbilt donde abordan una serie de aspectos y patrones en sincronización de datos en el diseño de aplicaciones móviles.

Almacenamiento Local (WebSQL y IndexedDB. LocalStorage SessionStorage)

En este caso abordamos tecnologías propias del navegador para almacenar información del lado del cliente, por ende nos adentramos en el mundo del soporte de los navegadores y las especificaciones que establece el W3C (World Wide Web Consortium) sobre HTML y CSS, por lo cual al usar estas tecnologías debemos determinar el navegador usado las soporta, ya bien manualmente o mediante Modernizr. No ahondare mucho en la implementación y uso de las tecnologías pero si dejare algunos ejemplos, considero que algunas de estas merecen publicaciones propias para darles el valor que merecen.

WebSQL

Es una especificación hecha por el W3C que intentó traer SQL al cliente, sin embargo las diferentes complicaciones hicieron que el grupo de trabajo encargado decidiera no seguir con esta tecnología como especifican en la nota del 18 de noviembre del 2010, razón por la cual no ahondaremos mucho en el asunto.

LocalStorage

Esta especificación tiene varios nombres, se le llama LocalStorage, DomStorage y por su nombre real WebStorage. Ya que de acuerdo a la especificación LocalStorage es uno de los “espacios” designados para usar esta característica, este espacio es compartido por “origen” es decir por los componentes que definen un origen en la política del mismo origen (same origin policy), es decir, la combinación de protocolo, hostname y número de puerto. En html5rocks y diveintohtml5 pueden conseguir más información al respecto y tutoriales bien desarrollados.

Un poco de código puede ilustrar el uso de esta herramienta. Debemos tomar en cuenta que solo se pueden almacenar cadenas mediante la API de Storage e intentar insertar otro tipo de dato forzará una conversión a cadenas, por lo cual puede ser una buena alternativa convertir nuestros objetos a JSON y almacenarlos y hacer lo inverso al obtenerlos. Este ejemplo levanta alerts para mostrar los valores guardados por cada clave.

SessionStorage

Es el otro espacio designado para almacenamiento local en la especificación de WebStorage, a diferencia de LocalStorage SessionStorage expira por sesión, es decir la duración y ámbito de SessionStorage difiere de la LocalStorage por lo cual vale la pena estar claro de sus diferencias, apartando esto, ambas pueden proveer una mejor alternativa a las cookies en dos aspectos, primero, WebStorage no es enviado en cada petición HTTP como las cookies además de que el espacio con el que cuenta es mucho mayor que los 4KB asignados a las cookies.

IndexedDB

Es una especificación más reciente que brinda una API para un almacén de objetos. Todavía su soporte no es tan amplio como el de otras tecnologías pero está pensada de una manera distinta a WebSQL, por ejemplo el artículo del MDN de Mozilla podemos ver una introducción y explicación bien completa de la API. A diferencia de WebStorage IndexedDB puede efectuar sus transacciones de manera asíncrona, cosa que WebStorage no puede, lo que significa que puede haber un impacto en las respuestas de tu aplicación si la cantidad de datos que usas con WebStorage es de cierto tamaño. Este bloqueo a la interfaz del usuario no se presenta con IndexedDB porque todas implementaciones que hasta el momento se tienen funcionan de manera asíncrona.

Otra característica que podemos ver con IndexedDB es que esta no funciona como una base de datos relacional (RDBMS) y supone una barrera de entrada un poco más alta que usar WebStorage, por ejemplo en html5rocks tienen un tutorial sobre el uso de IndexedDB y cómo usarlo en el contexto de una aplicación pensada para usar WebSQL. Tengo pensado dedicar un post en el futuro solo para Indexed DB.

Hay algo que tomar en cuenta, estas herramientas todavía no logran darnos una webapp offline. Solo tenemos la capacidad de guardar cierta cantidad de información del lado del cliente. Eso no elimina el problema de que cuando el usuario desee cambiar de página no podrá usarla por la falta de conexión, aquí es donde entra nuestra próxima posibilidad.

Cache Usando manifest=”app.appcache”

Empezamos por detectar si el cliente está conectado haciendo uso de navigator.onLine que es una propiedad que está presente en los navegadores de uso común, sin embargo vale la pena determinar que significa en cada navegador, de acuerdo al artículo de la MDN sobre esta propiedad en Chrome y Safari podemos obtener falsos positivos en cuanto a la conexión.

Como segundo paso es necesario crear un archivo que llamaremos appoffline.manifest, este archivo es una lista de los archivos que deben ser descargados en el cliente para garantizar el uso offline de la aplicación y su tipo MIME debe ser text/cache-manifest MIME-type, un ejemplo muy sencillo de un documento de este tipo está en sitepoint:

CACHE MANIFEST
styles.css
jquery-1.4.min.js
offline.js
index.html

Después de esto debemos enlazarlo en la etiqueta html

<html manifest="appoffline.manifest">

Es necesario que este documento este referenciado en cada página que queremos que sea descargada al cliente. O podemos en sentido inverso especificar en el documento todas aquellas páginas que queremos que sean descargadas al cliente, ya que solo se descargará si está escrito en el manifiesto.

Esta herramienta tiene muchos detalles dentro de la especificación de su estructura que pueden ser usados con mucha facilidad para nuestro beneficio, aquí les dejo una serie de recursos para que los exploren a profundidad y puedan determinar cual les beneficia más.

A Beginner’s Guide to Using the Application Cache – HTML5 rocks

How To Create an Offline Web Application – Sitepoint

LET’S TAKE THIS OFFLINE – Dive into HTML5

Conclusión

Para concluir podemos ver la multitud de posibilidades que hay para poder lograr esas capacidades de sincronización y trabajo offline. Nuevamente se presenta uno de esos casos donde el uso de la técnica o herramienta no depende de cual es mejor por si sola sino cual se adapta y resuelve de la manera adecuada el problema que estamos enfrentando y facilita en algunos casos el uso y acceso de las herramientas que desarrollamos.


Anuncios

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s