Introducción a los Service Workers

 

 

Service Worker, el santo grial de PWA o aplicaciones web progresivas. Pero, ¿qué es un PWA?.

Google dice algo poco específico, son “experiencias”, otros llaman “aplicaciones web progresivas”, otros “como aplicaciones nativas”, pero para todos ustedes la explicación más fácil es que una PWA es una aplicación web con, al menos, un trabajador de servicios con caché.

Hace tiempo, habrás visto tipos de web (por ejemplo, un chat) que se comunican con un servidor y devuelven (y envían) texto a un grupo de personas. O bien, antes de frameworks como AngularJS (o angular, o el framework típico o biblioteca), o incluso la ejecución en segundo plano del código dentro de su navegador.

Web Worker

Lo que os acabo de contar es un Web Worker. Un web worker es una pieza de código (javascript) que puede ejecutar en su navegador en segundo plano y puede comunicarse para enviar y recibir “mensajes”. Su uso, aunque sencillo en si, era complicado para la mayoría de la gente con todas las ventajas que ofrecía hasta la creación de frameworks y bibliotecas (Angular, React, Vue, esas cosas…).

Por ejemplo, un web worker típico para conocer números primos será así:

El archivo HTML:

<h1>Prime number worker</h1>
<article>Primer numerb!: 
<div id="result"> </div>
 

</article>poner ahí ficheros de la aplicación y creamos un método para capturar las operaciones de fetch de tu página web, si pedimos algo que tenga en la cache (por ejemplo) si no tienes conexión, la web funcionara como una aplicación... y ya tenemos una PWA.

Vamos a hacer un ejemplo, primero el HTML:







 

<center><img></center> 

<script>if ('serviceWorker' in navigator) {<br />
        window.addEventListener('load', function() {<br />
          navigator.serviceWorker.register('service.js')<br />
          .then(function(registration) {<br />
           // Successful registration<br />
           console.log('Hooray. Registration successful, scope is:', registration.scope);<br />
          }).catch(function(err) {<br />
           // Failed registration, service worker won’t be installed<br />
           console.log('Whoops. Service worker registration failed, error:', err);<br />
          });<br />
        });<br />
      }</p>
<p>      // Fetch example<br />
      var Image = document.querySelector('img');</p>
<p>      fetch('flores.jpg')<br />
      .then(function(response) {<br />
        console.log('Fetching on the page ok!');<br />
        return response.blob();<br />
      })<br />
      .then(function(myBlob) {<br />
        var objectURL = URL.createObjectURL(myBlob);<br />
        Image.src = objectURL;<br />
      });</p>
<p>    </script>


Y ahora el fichero service.js

// Vars
const PRECACHE = 'precache-v1';
const RUNTIME = 'runtime';
var CACHE_NAME = 'my-first-serviceworker';
var urlsToCache = [
'//flores.jpg',
'index.html',
];

self.addEventListener('install', function(event) {
console.log('Installing!');
event.waitUntil(
caches.open(CACHE_NAME)
.then(function(cache) {
console.log('Addiding files to cache!');
console.log(cache);
// Open a cache and cache our files
return cache.addAll(urlsToCache);
})
// Skip waiting if it's on the cache
.then(self.skipWaiting())
);
});

// Activate event
self.addEventListener('activate', function(event) {
console.log('Activating event '+ event);
});

//Control fetch
self.addEventListener('fetch', function(event) {
console.log('Fetching some data');
console.log(event.request.url);
event.respondWith(
caches.match(event.request).then(function(response) {
console.log('File is on the cache! Hooray! Let\'s take it from there!');
return response || fetch(event.request);
})
);
});

Aunque parezca muy complicado es muy muy sencillo. Observando el fichero html verás que hay un tag "img" vacio, no apunta a ningún sitio y por lo tanto no cargaría absolutamente nada pero, en el javascript veras que hay un fetch que, realmente, hace una petición de un fichero y carga una imagen (cualquiera, en mi caso unas flores).

Ademas, en el HTML vemos como se instala el worker preguntando al navegador si tiene capacidad de aceptar service worker. Si la respuesta es afirmativa, se registra y punto pelota.

Hay diferentes formas, pero la mas usual es la que veis, añadir un evento al load de la pagina que sea registrar el service worker con un promise (que nunca se sabe) a fin de poder mandarle a otras versiones o hacer otras cosas si no funciona.

En el worker (el fichero javascript) que es el que compone el service worker verás ciertas cosas importantes, vamos, el mejunje de un service worker.

Lo primero a tener en cuenta es que lo que haremos realmente sera que todo lo controlamos a traves de los eventos del navegador. Es decir, controlaremos los eventos.

Si observais, vereis que todo se llama a traves del self porque este hace referencia a la ventana de forma que no afecte al resto de pestañas o ventanas que tenga el navegador abiertas.

¿Y que eventos son los que tenemos que tener en cuenta?. Aunque hay muchos ejemplos, los principales a usar son install, fetch y activate.

El evento install se dispara cuando, obviamente, se instala el service worker. Normalmente se usa para crear las condiciones necesarias para que el service worker funcione por ejemplo la cache, meter los ficheros en ella y todas esas cosas. Recodad que se dispara una unica vez y solo cuando se instala.

El evento activate se dispara cuando se activa el service worker, antes de realizar cualquier acción. Normalmente se usa para revisar la cache (por si cambia) o incluso para instalar una versión mejor del propio service worker (por si actualizais el código y esas cosas... recordad que la comparación es binaria).

Y por último, el evento fetch se dispara cuando la ventana realiza un fetch, es decir, una petición. Se suele usar para lo que veis en el ejemplo, interceptarlo, revisar si el fichero esta en la cache o no y enviarlo de la misma.

Por lo tanto, en el ejemplo, hemos creado una cache que, si no esta conectado a red, mostrara la imagen de las flores igualmente e incluso si esta conectado a red al cargarlo de la cache ira mucho más rápido.

Luego a partir de aquí podéis hacer lo que mas os guste como por ejemplo cargar imágenes "vacías" que hagan de placeholder de objetos. Esto seguro que lo habéis visto en Youtube o en Facebook (por poner dos ejemplos) que muestra placeholders mientras se trae vuestras notificaciones o los videos o lo que sea de forma que, al usuario, le hace más agradable la espera y no le cambia todo de golpe.

Por supuesto hay muchos más eventos que se pueden controlar desde un service worker. Os recomiendo echarle un ojo a este repositorio en GitHub donde hay muchisimos ejemplos: https://github.com/GoogleChrome/samples/tree/gh-pages/service-worker

Bueno, esto es el típico service worker. Si lo ejecutáis y abrís la consola del navegador, veréis (por el código) que va haciendo y donde, porque siempre es bueno para aprender.

Y por supuesto, se pueden hacer muchas cosas, pero esto es una simple introducción.

Publicado por mi: Linkedin (english)

tuti

Técnico en Comunicación Interna de la UVa

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.