Aplicaciones web progresivas: Cómo desconectarse

1. Bienvenida

En este lab, tomará una aplicación web existente y hará que funcione sin conexión. Este es el primero de una serie de codelabs complementarios para el taller de apps web progresivas. Hay siete codelabs más en esta serie.

Qué aprenderás

  • Escribe un service worker manualmente
  • Cómo agregar un service worker a una aplicación web existente
  • Usa el service worker y la API de Cache Storage para habilitar el acceso sin conexión a los recursos

Lo que debe saber

  • HTML básico y JavaScript

Qué necesitarás

2. Prepárate

Comienza por clonar o descargar el código de inicio necesario para completar este codelab:

Si clonas el repositorio, asegúrate de estar en la rama starter. El archivo ZIP también contiene el código de esa rama.

Esta base de código requiere Node.js 14 o una versión posterior. Una vez que tengas el código disponible, ejecuta npm ci desde la línea de comandos de la carpeta del código para instalar todas las dependencias que necesitarás. Luego, ejecuta npm start para iniciar el servidor de desarrollo del codelab.

El archivo README.md del código fuente proporciona una explicación para todos los archivos distribuidos. Además, los siguientes son los archivos existentes clave con los que trabajarás en este codelab:

Archivos clave

  • js/main.js: Archivo JavaScript principal de la aplicación
  • service-worker.js: Archivo de service worker de la aplicación

3. Prueba sin conexión

Antes de realizar cualquier cambio, probemos si la aplicación web no funciona sin conexión en este momento. Para ello, deja la computadora sin conexión y vuelve a cargar la app web. Si usas Chrome, sigue estos pasos:

  1. Cómo abrir las herramientas para desarrolladores de Chrome
  2. Cambia a la pestaña Application
  3. Cambia a la sección Service workers
  4. Marca la casilla de verificación Sin conexión.
  5. Cómo actualizar la página sin cerrar las Herramientas para desarrolladores de Chrome

La pestaña Aplicación de las herramientas para desarrolladores de Chrome abierta a los service workers con la casilla de verificación Sin conexión marcada

Dado que el sitio se probó y no se cargó correctamente, es hora de agregar algunas funcionalidades en línea. Desmarca la casilla de verificación sin conexión y continúa con el siguiente paso.

4. Desconectar

Es el momento de agregar un service worker básico. Esto ocurrirá en dos pasos: registrar el service worker y almacenar los recursos en caché.

Registra un service worker

Ya existe un archivo de service worker vacío; por lo tanto, para asegurarte de que se muestren los cambios, regístralo en nuestra aplicación. Para ello, agrega el siguiente código a la parte superior de js/main.js:

import swURL from 'sw:../service-worker.js';

// Register the service worker
if ('serviceWorker' in navigator) {
  // Wait for the 'load' event to not block other work
  window.addEventListener('load', async () => {
    // Try to register the service worker.
    try {
      const reg = await navigator.serviceWorker.register(swURL);
      console.log('Service worker registered! 😎', reg);
    } catch (err) {
      console.log('😥 Service worker registration failed: ', err);
    }
  });
}

Explicación

Este código registra el archivo vacío de service workers service-worker.js una vez que se carga la página, y solo si el sitio admite service workers.

Recursos del almacenamiento en caché previo

Para que la aplicación web funcione sin conexión, el navegador debe poder responder a las solicitudes de red y elegir la ruta. Para ello, agrega lo siguiente a service-worker.js:

// Choose a cache name
const cacheName = 'cache-v1';
// List the files to precache
const precacheResources = ['/', '/index.html', '/css/style.css', '/js/main.js', '/js/app/editor.js', '/js/lib/actions.js'];

// When the service worker is installing, open the cache and add the precache resources to it
self.addEventListener('install', (event) => {
  console.log('Service worker install event!');
  event.waitUntil(caches.open(cacheName).then((cache) => cache.addAll(precacheResources)));
});

self.addEventListener('activate', (event) => {
  console.log('Service worker activate event!');
});

// When there's an incoming fetch request, try and respond with a precached resource, otherwise fall back to the network
self.addEventListener('fetch', (event) => {
  console.log('Fetch intercepted for:', event.request.url);
  event.respondWith(
    caches.match(event.request).then((cachedResponse) => {
      if (cachedResponse) {
        return cachedResponse;
      }
      return fetch(event.request);
    }),
  );
});

Ahora, regrese al navegador, cierre la pestaña de vista previa y vuelva a abrirla. Deberías ver objetos console.log que corresponden a los diferentes eventos en el service worker.

A continuación, vuelve a conectarte y actualiza el sitio. Debería ver que se carga aunque esté sin conexión.

Explicación

Durante el evento de instalación del service worker, se abre una memoria caché con la API de almacenamiento en caché. Luego, los archivos y las rutas especificados en precacheResources se cargan en la caché con el método cache.addAll. Esto se denomina almacenamiento previo en caché porque almacena en caché de forma preventiva el conjunto de archivos durante el tiempo de instalación, en lugar de almacenarlos en caché cuando se necesitan o se solicitan.

Una vez que el service worker controla el sitio, los recursos solicitados pasan por él como un proxy. Cada solicitud activa un evento de obtención que, en este service worker, busca en la caché una coincidencia, si existe una coincidencia, responde con un recurso almacenado en caché. Si no hay coincidencia, el recurso se solicita normalmente.

El almacenamiento en caché de los recursos permite que la app funcione sin conexión, ya que evita solicitudes de red. Ahora, la app puede responder con un código de estado 200 cuando no hay conexión.

5. ¡Felicitaciones!

Aprendiste cómo hacer que tu aplicación web esté sin conexión mediante service workers y la API de almacenamiento en caché.

El siguiente codelab de la serie es Cómo trabajar con la caja de trabajo