Recursos
- HTML5 Rocks! | Offline
- MDN | Eventos online y offline
- HTML5 Rocks! | "Offline": What does it mean and why should I care?
- Trabaja offline gracias a la API de caché de HTML5
- MDN | Usar el caché de aplicaciones
- Ebook | Pro HTML5 Programming | Chapter 12: Creating HTML5 Offline Web Applications
- HTML5 Docter | let’s take this offline
- W3C Spec | Offline
- TheFox/html5-offline-example
- Tutorial: How to make an offline HTML5 web app, FT style
- How To Use HTML5 Offline Storage In Your Website
- Offline-capable applications with HTML5
- Offline Application: using manifest
- Researching HTML5 Offline
Uso y limitaciones
- Aplicación disponible independientemente del estado de la conexión
- Se acelera la carga de los archivos
- Disminuyen las consultas al servidor
- En algunos navegadores es necesario que el usuario permita el almacenamiento
- Para incluir cambios en la aplicación es necesario modificar el manifiesto
if (!window.applicationCache) {
console.warn("No se puede utilizar applicationCache :-(");
} else {
console.log("Podemos utilizar applicationCache :-)");
}
if (window.navigator.onLine) {
const detalles = `<h1>Estas Conectado a Internet!!</h1>
<h3>Detalles del navegador:</h3>
<p>CodeName: ${navigator.appCodeName}</p>
<p>Nombre: ${navigator.appName}</p>
<p>Versión: ${navigator.appVersion}</p>
<p>Cookies Habilitadas: ${navigator.cookieEnabled}</p>
<p>Lenguaje: ${navigator.language}</p>
<p>Plataforma: ${navigator.platform}</p>
<p>User-agent header: ${navigator.userAgent}</p>`;
document.body.innerHTML = detalles;
} else {
document.body.innerHTML = "<h1>No estas Conectado!!</h1>"
console.warn("No estamos conectados a Internet!");
}
- Verificando la conexión usando eventos:
window.addEventListener("offline", () => {
console.warn("Estas desconectado!")
});
window.addEventListener("online", () => {
console.info("Estas conectado!")
});
Uso
- Los archivos son visibles en la pestaña Resources/Application Cache
- El atributo manifest puede señalar a una URL pero deben tener el mismo origen que la aplicación web
- Los sitios no pueden tener más de 5MB de datos almacenados en caché, pueden ser menos si el usuario lo cambia.
- Si no se puede descargar el archivo de manifiesto o algún recurso especificado en él, fallará todo el proceso de actualización de la caché.
- Añadir la versión del manifest como comentario.
- JAMAS incluir el propio manifest dentro del manifest
- Es necesario ajustar el MIME en algunos servidores
// Ex: Apache
AddType text/cache-manifest .appcache
Nuevo sistema de carga
- Si existe manifest, el navegador carga el documento y sus recursos asociados directamente desde local.
- Se verifica si hubo actualizaciones al manifest.
- Si se actualizo, el navegador descarga la nueva versión del archivo y de los recursos listados en él (segundo plano).
Estructura
CACHE
lo que se cachearáNETWORK
lo que NO se cachearáFALLBACK
que se visualizará si algo no esta disponible de manera offline
Incluyendo el manifest
<html manifest="ejemplo.appcache">
<!-- ... -->
</html>
Ejemplo de Manifest
CACHE MANIFEST
# versión 1.0
# SI CACHEAR
CACHE:
index.html
offline.html
css/style.css
js/script.js
img1.jpg
img2.jpg
img3.jpg
logo.png
# Mostraremos offline.html cuando algo falle
FALLBACK:
offline.html
# NO CACHEAR
NETWORK:
*
# * es todo aquello que no este en CACHE
const appCache = window.applicationCache;
switch (appCache.status) {
case appCache.UNCACHED: // appCache.status == 0
console.warn('Un objeto caché de la aplicación no se inicializó correctamente o falló.');
break;
case appCache.IDLE: // appCache.status == 1
console.info('La caché no esta en uso.');
break;
case appCache.CHECKING: // appCache.status == 2
console.info('El manifesto se ha obtenido y esta siendo revisado para actualizarse.');
break;
case appCache.DOWNLOADING: // appCache.status == 3
console.info('Se estan descargando nuevos recursos debido a una actualización del manifesto.');
break;
case appCache.UPDATEREADY: // appCache.status == 4
console.info('Hay una nueva versión del manifiesto.');
break;
case appCache.OBSOLETE: // appCache.status == 5
console.info('El caché esta ahora obsoleto');
break;
default:
console.warn('El Caché esta en estado desconocido');
break;
};
function eventosCache(){
const appCache = window.applicationCache;
appCache.addEventListener('cached', chivato);
appCache.addEventListener('checking', chivato);
appCache.addEventListener('downloading', chivato);
appCache.addEventListener('error', chivato);
appCache.addEventListener('noupdate', chivato);
appCache.addEventListener('obsolete', chivato);
appCache.addEventListener('progress', chivato);
appCache.addEventListener('updateready', chivato);
function chivato(e) {
const conexion = (navigator.onLine) ? 'sí': 'no';
const type = e.type;
console.log(`Conectado: ${conexion}, Evento: ${type}, \nMás Información: %O`, e);
}
}
Forzar la actualización (manualmente)
const appCache = window.applicationCache;
appCache.update(); // Intentamos actualizar la versión del usuario con un nuevo manifest
if (appCache.status == window.applicationCache.UPDATEREADY) {
appCache.swapCache(); // La ctualización es correcta y se cambiado a la nueva versión
}
- Los Web Workers se ejecutan en un subproceso aislado.
- Funcionan aunque la pagina se haya cerrado
- Siguen funcionando aunque el navegadro se cierre.
- Especificación
- Soporte
Arquitectura
Alcance
- En el contexto de un Worker, tanto self como this hacen referencia al alcance global del Worker
- Puede acceder a:
- Objeto navigator
- Objeto location (de solo lectura)
- XMLHttpRequest
- setTimeout(), setInterval(), etc...
- Caché de la aplicación
- Importación de secuencias de comandos externas, importScripts()
- Generación de otros Web Workers
Limitaciones
- No se ejecutarán de forma local
- DOM
- Objeto window
- Objeto document
- Objeto parent
Recomendaciones
- Obtención previa y/o almacenamiento en caché de datos para un uso futuro
- Métodos para destacar la sintaxis de código u otros formatos de texto en tiempo real
- Corrector ortográfico
- Análisis de datos de vídeo o audio
- Entrada y salida en segundo plano o solicitud de servicios web
- Procesamiento de conjuntos o respuestas JSON de gran tamaño
- Filtrado de imágenes en
- Actualización de varias filas de una base de datos web local
Ejemplos
Recursos
- Introducción a los Web Workers en html5rocks
- Web workers without a separate Javascript file?
- Offline Recipes for Service Workers by DWB
- Using Web Workers to Speed-Up Your JavaScript Applications by treehouse
- Debugging Web Workers with Chrome Developer Tools
- Using Web Workers en MDN
- Concurrency in JavaScript
Librerías
Definición y puesta en marcha
- Instanciando el Web Worker
const worker = new Worker('fichero.js');
- Arrancando el Web Worker
const worker = new Worker('fichero.js');
worker.postMessage();
Comunicación
- Desde el archivo principal
const worker = new Worker('fichero.js');
worker.addEventListener('message', evento => {
console.log('El worker dice: ', evento.data);
}, false);
worker.postMessage('Hola Mundo!');
- Desde el Web Worker
self.addEventListener('message', evento => {
self.postMessage(evento.data);
}, false);
Parar un Web Worker
- Desde el archivo principal
worker.terminate()
- Desde el Web Worker
self.close()
Subworkers
- La resolución de las URI de los Subworkers está relacionada con la ubicación de su Worker principal (en oposición a la página principal)
- Los Workers tienen la capacidad de generar Workers secundarios.
- Los Subworkers deben estar alojados en el mismo origen que la página principal.
Blob En el HTML:
<!-- inline worker -->
<script id="worker" type="javascript/worker">
((s => {
const increment = 1;
let count = 0;
const loop = 999999999;
s.onmessage = e => {
console.log(e.data);
let test = 0;
for( let i = 0 ; i < loop ;i++ ){
test = i;
const int = Math.trunc( i*100/loop );
if( int === count ){
s.postMessage( int );
count += increment;
}
}
s.postMessage( {finish:'loop finished'} );
};
}))(self);
</script>
En JS:
const blob = new Blob([document.querySelector('#worker').textContent], { type: "text/javascript" });
const worker = new Worker(window.URL.createObjectURL(blob));
Shared Web Workers
Definición y puesta en marcha
- Instanciando el Web Worker
const worker = new SharedWorker("fichero.js");
- Arrancando el Web Worker utiliznado port
const worker = new SharedWorker("/html5/web-worker-shared.jsp");
worker.port.addEventListener("message", event => {
console.log("datos del ShraedWorker", event.data);
}, false);
worker.port.start();
Comunicación
- Desde el archivo principal
const worker = new SharedWorker("/html5/web-worker-shared.jsp");
worker.port.addEventListener("message", event => {
console.log("datos del ShraedWorker", event.data);
}, false);
worker.port.postMessage("First Message");
- Desde el Web Worker
const ports = [];
onconnect = event => {
const port = event.ports[0];
ports.push(port);
port.start();
port.addEventListener("message", event => { listenForMessage(event, port); } );
}
listenForMessage = (event, port) => {
port.postMessage(`Reply from SharedWorker to: ${event.data}`);
}
//Implementation of shared worker thread code
setInterval(() => { runEveryXSeconds() }, 5000);
function runEveryXSeconds() {
for(i = 0; i < ports.length; i++) {
ports[i].postMessage(`Calling back at : ${new Date().getTime()}`);
}
}