Por Nick Heath en Developer el 30 de octubre de 2014, 5:10 AM PST
Un vistazo a cómo la integración de la funcionalidad offline en aplicaciones web podría ser pronto mucho más fácil utilizando a los trabajadores de servicio.
Construir aplicaciones web que funcionen bien fuera de línea puede seguir siendo un proceso difícil y frustrante para los desarrolladores.
Sin embargo, como parte de los esfuerzos para cerrar la brecha con las aplicaciones nativas, los fabricantes de navegadores buscan simplificar la creación de aplicaciones web que funcionen cuando la red no funciona.
Se suponía que la caché de aplicaciones en la especificación HTML5 proporcionaba una forma relativamente fácil para que las aplicaciones web funcionaran sin conexión, pero se quedó corta en varios aspectos importantes, como no cargar automáticamente contenido nuevo una vez que los datos habían sido almacenados en caché. Como resultado, la caché de aplicaciones ha sido objeto de duras críticas.
Google y Mozilla están buscando formas de crear aplicaciones web»offline-first», en las que todo lo que la aplicación necesita para funcionar, al menos en su forma más básica, se almacena en el dispositivo y sólo necesita conectarse a la red para obtener nuevos datos.
Para Mozilla, mejorar estas capacidades fuera de línea es importante para el SO Firefox, su sistema operativo móvil de código abierto diseñado para ejecutar aplicaciones creadas a partir de tecnologías web como HTML, CSS y JavaScript (JS. Los primeros teléfonos que ejecutan el sistema operativo se lanzaron en regiones como Europa del Este y América del Sur, áreas cuya infraestructura de red es tal que las aplicaciones no pueden asumir una conexión de red.
Para ayudar a los desarrolladores a crear aplicaciones web que funcionen sin problemas sin conexión, Google y Mozilla están implementando compatibilidad con la especificación W3C Service Workers.
Los trabajadores de servicios son scripts JavaScript controlados por eventos que se ejecutan independientemente de las páginas web y controlan la forma en que reciben los datos.
Lo que hará que los scripts de Service Worker sean tan útiles a la hora de crear aplicaciones fuera de línea es su capacidad para interceptar peticiones de red y servir contenido desde su propia caché de scripts.
Las próximas versiones de Chrome 40 y aún no especificadas de Firefox y Firefox OS incluirán soporte para lo que probablemente serán implementaciones compatibles de Service Workers. El soporte para los trabajadores de servicio puede activarse en los navegadores Chrome Canary, Firefox Nightly y Opera mediante ajustes de configuración.
Para empezar a utilizar un Trabajador de Servicios, un desarrollador debe registrar primero el script del trabajador en un archivo JavaScript utilizado por su aplicación o página. Esto se hace llamando al método serviceWorker.register() y pasando la ruta al archivo de script del trabajador del servicio como argumento.
if (‘serviceWorker’ en el navegador) {
navigator.serviceRegistro.del.trabajador(‘/sw-test/sw.js’, {
alcance: « /sw-test».
).entonces(función(sw) {
// registro trabajado
console.log (‘Registro exitoso’);
catch(función(error) {}.catch(función(error)
// Falló la inscripción
console.log (‘Registration failed with ‘ + error);
});
}
Una vez registrado, el script podrá interceptar todas las peticiones realizadas por páginas cargadas posteriormente que se encuentren dentro de su ámbito de aplicación, como sw-test/index.html o sw-test/mouse/trap.html en el ejemplo anterior. Una vez registrado el script, el método devuelve una promesa.
Por defecto, el alcance de los Trabajadores de Servicio en Chrome 40 estará limitado por la ubicación del script Service Worker, por lo que un script en /answers/sw.js sólo podrá controlar las solicitudes de navegación de los documentos cuya URL haya comenzado con /answers.
Configuración de la caché
Una vez que un Trabajador de Servicios se haya registrado, será instalado y activado por el navegador.
Una vez finalizada la instalación, es un buen momento para rellenar la caché del Service Worker con los recursos que desea que estén disponibles localmente.
Una vez finalizada la instalación, se dispara un evento de instalación, que puede detectarse registrando un escuchador de eventos dentro del script Service Worker. A este oyente se le puede pasar una función que llena la caché.
this.addEventListener(‘instalar’, function(event) {
event.waitUntil(cachesPolyfill.open(‘demo-cache’.then(function(cache) {
devolver cache.addAll(
/sw-test/»,
/sw-test/index.html»,
/sw-test/style.css’,
/sw-test/app.js»,
/sw-test/image-list.js»,
/sw-test/star-wars-logo.jpg’,
/sw-test/gallery/»,
/sw-test/gallery/image1.jpg’,
/sw-test/gallery/image2.jpg».
);
})
);
});
Aquí el método cachesPolyfill.open() crea una nueva caché llamada demo-cache, que será la caché de recursos del sitio. Esto devuelve una promesa para una caché creada. Una vez cumplida la promesa, una función llama al método addAll() en la caché, que para sus parámetros lleva una lista de URLs relativas al origen a todos los recursos que desea almacenar en caché.
La API de caché de Service Worker está pensada para funcionar de forma similar a la caché estándar del navegador, pero es específica para un dominio web.
El detalle de cómo lograr esto podría cambiar debido a que la API de caché no está finalizada, con la funcionalidad que proporciona actualmente un polifiltro de JavaScript que necesita ser importado por el script Service Worker.
Sin embargo, Google tiene la intención de implementar soporte para un subconjunto de la API de caché de Service Worker en Chrome 40.
Asegurarse de que su aplicación funciona sin conexión
Dirigir el navegador para que extraiga datos y recursos de la caché, en lugar de hacerlo a través de la red, se consigue escuchando el evento fetch. El oyente del evento debe estar registrado en el script Service Worker.
El evento fetch se dispara cada vez que se obtiene un recurso -como imágenes, archivos CSS y JS- que se encuentra en el ámbito del Service Worker. También se dispara cuando un documento controlado por un Trabajador de Servicios solicita un recurso, incluso si ese recurso es de un origen diferente.
self.addEventListener(‘buscar’, función(event) {
console.log(solicitud.de.evento);
});
Como señaló el desarrollador de Google Jake Archibald en su explicación para los trabajadores de servicios, cuando se combina con el método respondWith() de event, esto proporciona la capacidad de secuestrar una solicitud e inyectar su propia respuesta.
self.addEventListener(‘buscar’, función(event) {
event.respondWith(new Response(«Hello world!»));
});
O en este ejemplo capturando todas las peticiones de imágenes jpg y reemplazándolas con un garabato de Google.
self.addEventListener(‘buscar’, función(event) {
si (/\.jpg$/.test(event.request.url)) { /\.jpg$/.test
event.respondWith( fetch(‘//www.google.co.uk/logos/…3-hp.gif’, {
modo:’no-cors’.
}) );
}
});
Dirigir la página para extraer recursos de la caché en lugar de a través de la red funciona de forma similar a lo anterior, como se muestra en este ejemplo, donde el método match() comprueba cada recurso solicitado de la red contra la caché y devuelve el recurso relevante si está disponible.
self.addEventListener(‘buscar’, función(event) {
event.respondWith( cachesPolyfill.match(solicitud.de.evento.then(function(response) {
respuesta de retorno || fetch(event.request);
}) );
});
Los trabajadores de servicio pueden secuestrar conexiones, responder de forma diferente y filtrar respuestas, capacidades que podrían utilizarse en un ataque de hombre en el medio. Para evitarlo, sólo es posible registrar a los trabajadores de servicio en las páginas servidas a través de HTTPS.
Los trabajadores de servicio también pueden ser iniciados por navegadores u otros agentes de usuario sin un documento adjunto y pueden ser eliminados por el agente de usuario en casi cualquier momento. Su capacidad para responder a los eventos cuando una página no está abierta permite que se utilicen para controlar procesos de fondo como la mensajería Push y la sincronización en segundo plano.
Todavía es pronto para los trabajadores de servicios y los detalles de las implementaciones en los principales navegadores están sujetos a cambios, pero para obtener más información, lea esta explicación de Google’s Archibald o este resumen de Mozilla Developer Network, de donde provienen muchos de estos ejemplos.