Este codelab forma parte del curso de capacitación Developing Progressive Web Apps, desarrollado por el equipo de capacitación de Google Developers. Aprovecharás al máximo este curso si trabajas con los codelabs de forma secuencial.
Para obtener detalles completos sobre el curso, consulta la descripción general de Developing Progressive Web Apps.
Introducción
En este lab, se explica cómo crear un service worker simple y su ciclo de vida.
Qué aprenderás
- Crea una secuencia de comandos básica del trabajador de servicio, instálala y realiza una depuración simple
Lo que debe saber
- Conocimientos básicos de JavaScript y HTML
- Conceptos y sintaxis básica de las promesas de ES2015
- Cómo habilitar la consola para desarrolladores
Qué necesitas antes de comenzar
- Una computadora con acceso a la terminal o al shell
- Conexión a Internet
- Un navegador que admita Service Workers
- Un editor de texto
Descarga o clona el repositorio de pwa-training-labs desde GitHub y, si es necesario, instala la versión LTS de Node.js.
Navega al directorio service-worker-lab/app/ y, luego, inicia un servidor de desarrollo local:
cd service-worker-lab/app npm install node server.js
Puedes detener el servidor en cualquier momento con Ctrl-c.
Abre el navegador y navega a localhost:8081/.
Nota: Cancela el registro de todos los service workers y borra todas las memorias caché de service workers para localhost, de modo que no interfieran en el lab. En las Herramientas para desarrolladores de Chrome, puedes hacer clic en Borrar datos del sitio en la sección Borrar almacenamiento de la pestaña Aplicación.
Abre la carpeta service-worker-lab/app/ en tu editor de texto preferido. La carpeta app/ es donde compilarás el lab.
Esta carpeta contiene lo siguiente:
below/another.html,js/another.js,js/other.jsyother.htmlson recursos de muestra que usamos para experimentar con el alcance del service worker.- La carpeta
styles/contiene las hojas de estilo en cascada de este lab. - La carpeta
test/contiene archivos para probar tu progreso. index.htmles la página HTML principal de nuestro sitio o aplicación de ejemploservice-worker.jses el archivo JavaScript que se usa para crear nuestro service worker.package.jsonypackage-lock.jsonhacen un seguimiento de los paquetes de nodos que se usan en este proyecto.server.jses un servidor Express simple que usamos para alojar nuestra app.
Abre service-worker.js en tu editor de texto. Ten en cuenta que el archivo está vacío. Aún no agregamos ningún código para que se ejecute en el service worker.
Abre index.html en tu editor de texto.
Dentro de las etiquetas <script>, agrega el siguiente código para registrar el service worker:
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('service-worker.js')
.then(registration => {
console.log('Service Worker is registered', registration);
})
.catch(err => {
console.error('Registration failed:', err);
});
});
}Guarda el código y actualiza la página. La consola debería devolver un mensaje que indique que se registró el service worker. En Chrome, puedes verificar que se haya registrado un service worker. Para ello, abre Herramientas para desarrolladores (Ctrl + Mayúsculas + I en Windows y Linux, o bien ⌘ + Opción + I en Mac), haz clic en la pestaña Application y, luego, en la opción Service Workers. Debería ver un resultado similar al siguiente:

Opcional: Abre el sitio en un navegador no compatible y verifica que la condicional de verificación de compatibilidad funcione.
Explicación
El código anterior registra el archivo service-worker.js como un trabajador de servicio. Primero, verifica si el navegador admite Service Workers. Esto se debe hacer cada vez que registres un service worker, ya que es posible que algunos navegadores no los admitan. Luego, el código registra el trabajador de servicio con el método register de la API de ServiceWorkerContainer, que se encuentra en la interfaz Navigator de la ventana.
navigator.serviceWorker.register(...) devuelve una promesa que se resuelve con un objeto registration una vez que se registra correctamente el trabajador de servicio. Si falla el registro, se rechazará la promesa.
Los cambios en el estado del service worker activan eventos en el service worker.
Agrega objetos de escucha de eventos
Abre service-worker.js en tu editor de texto.
Agrega los siguientes objetos de escucha de eventos al trabajador de servicio:
self.addEventListener('install', event => {
console.log('Service worker installing...');
// Add a call to skipWaiting here
});
self.addEventListener('activate', event => {
console.log('Service worker activating...');
});Guarda el archivo.
Cancela el registro del service worker de forma manual y actualiza la página para instalar y activar el service worker actualizado. El registro de la consola debe indicar que se registró, instaló y activó el nuevo trabajador de servicio.
Nota: Es posible que el registro de inscripción aparezca desordenado con los otros registros (instalación y activación). El service worker se ejecuta de forma simultánea con la página, por lo que no podemos garantizar el orden de los registros (el registro de registro proviene de la página, mientras que los registros de instalación y activación provienen del service worker). La instalación, la activación y otros eventos del trabajador de servicio ocurren en un orden definido dentro del trabajador de servicio y siempre deben aparecer en el orden esperado.
Explicación
El service worker emite un evento install al final del registro. En el código anterior, se registra un mensaje dentro del objeto de escucha de eventos install, pero, en una app del mundo real, este sería un buen lugar para almacenar en caché los recursos estáticos.
Cuando se registra un service worker, el navegador detecta si es nuevo (ya sea porque es diferente del service worker instalado anteriormente o porque no hay ningún service worker registrado para este sitio). Si el service worker es nuevo (como en este caso), el navegador lo instala.
El service worker emite un evento activate cuando toma el control de la página. El código anterior registra un mensaje aquí, pero este evento se suele usar para actualizar cachés.
Solo un service worker puede estar activo a la vez para un alcance determinado (consulta Exploración del alcance del service worker), por lo que un service worker recién instalado no se activa hasta que el service worker existente ya no esté en uso. Por eso, todas las páginas controladas por un service worker deben cerrarse antes de que un nuevo service worker pueda tomar el control. Como cancelamos el registro del service worker existente, el nuevo se activó de inmediato.
Nota: No basta con actualizar la página para transferir el control a un nuevo service worker, ya que se solicitará la página nueva antes de que se descargue la página actual, y no habrá un momento en el que no se use el service worker anterior.
Nota: También puedes activar manualmente un nuevo service worker con la herramienta para desarrolladores de algunos navegadores y de forma programática con skipWaiting(), que analizamos en la sección 3.4.
Actualiza el service worker
Agrega el siguiente comentario en cualquier lugar de service-worker.js:
// I'm a new service workerGuarda el archivo y actualiza la página. Observa los registros en la consola. Verás que el nuevo service worker se instala, pero no se activa. En Chrome, puedes ver el service worker en espera en la pestaña Aplicación de Herramientas para desarrolladores.

Cierra todas las páginas asociadas con el Service Worker. Luego, vuelve a abrir localhost:8081/. El registro de la consola debería indicar que el nuevo service worker ya se activó.
Nota: Si obtienes resultados inesperados, asegúrate de que la caché HTTP esté inhabilitada en las herramientas para desarrolladores.
Explicación
El navegador detecta una diferencia de bytes entre el archivo del service worker nuevo y el existente (debido al comentario agregado), por lo que se instala el service worker nuevo. Dado que solo un service worker puede estar activo a la vez (para un alcance determinado), aunque se instale el nuevo service worker, no se activará hasta que el service worker existente deje de estar en uso. Cuando cerramos todas las páginas bajo el control del service worker anterior, podemos activar el nuevo service worker.
Cómo omitir la fase de espera
Es posible que un nuevo service worker se active de inmediato, incluso si hay un service worker existente, omitiendo la fase de espera.
En service-worker.js, agrega una llamada a skipWaiting en el objeto de escucha de eventos install:
self.skipWaiting();Guarda el archivo y actualiza la página. Observa que el nuevo trabajador de servicio se instala y activa de inmediato, incluso si un trabajador de servicio anterior estaba en control.
Explicación
El método skipWaiting() permite que un trabajador de servicio se active en cuanto finalice la instalación. El objeto de escucha de eventos de instalación es un lugar común para colocar la llamada a skipWaiting(), pero se puede llamar en cualquier lugar durante la fase de espera o antes de ella. Consulta esta documentación para obtener más información sobre cuándo y cómo usar skipWaiting(). Para el resto del lab, ahora podemos probar el nuevo código del service worker sin anular el registro del service worker de forma manual.
Más información
Los service workers pueden actuar como un proxy entre tu app web y la red.
Agreguemos un objeto de escucha de recuperación para interceptar las solicitudes de nuestro dominio.
Agrega el siguiente código a service-worker.js:
self.addEventListener('fetch', event => {
console.log('Fetching:', event.request.url);
});Guarda la secuencia de comandos y actualiza la página para instalar y activar el service worker actualizado.
Revisa la consola y observa que no se registraron eventos de recuperación. Actualiza la página y vuelve a revisar la consola. Esta vez, deberías ver eventos de recuperación para la página y sus recursos (como CSS).
Haz clic en los vínculos a Otra página, Otra página y Atrás.
Verás eventos de recuperación en la consola para cada una de las páginas y sus recursos. ¿Todos los registros tienen sentido?
Nota: Si visitas una página y no tienes inhabilitada la caché HTTP, es posible que los recursos CSS y JavaScript se almacenen en caché de forma local. Si esto sucede, no verás eventos de recuperación para estos recursos.
Explicación
El service worker recibe un evento de recuperación para cada solicitud HTTP que realiza el navegador y que se encuentra dentro de su alcance. El objeto del evento de recuperación contiene la solicitud. Escuchar eventos de recuperación en el service worker es similar a escuchar eventos de clic en el DOM. En nuestro código, cuando se produce un evento de recuperación, registramos la URL solicitada en la consola (en la práctica, también podríamos crear y devolver nuestra propia respuesta personalizada con recursos arbitrarios).
¿Por qué no se registró ningún evento de recuperación en la primera actualización? De forma predeterminada, los eventos de recuperación de una página no pasarán por un service worker, a menos que la solicitud de la página haya pasado por un service worker. Esto garantiza la coherencia en tu sitio. Si una página se carga sin el service worker, también lo hacen sus recursos secundarios.
Más información
- Fetch Event - MDN
- Uso de Fetch - MDN
- Introduction to Fetch - Google Developer (Introducción a Fetch - Google Developer)
Código de solución
Para obtener una copia del código que funciona, navega a la carpeta 04-intercepting-network-requests/.
Los Service Workers tienen alcance. El alcance del trabajador de servicio determina desde qué rutas intercepta solicitudes el trabajador de servicio.
Cómo encontrar el permiso
Actualiza el código de registro en index.html con lo siguiente:
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('service-worker.js')
.then(registration => {
console.log('SW registered with scope:', registration.scope);
})
.catch(err => {
console.error('Registration failed:', err);
});
});
}Actualice el navegador. Observa que la consola muestra el alcance del service worker (en este caso, es http://localhost:8081/).
Explicación
La promesa que muestra register() se resuelve en el objeto de registro, que contiene el alcance del Service Worker.
El alcance predeterminado es la ruta de acceso al archivo del service worker y se extiende a todos los directorios inferiores. Por lo tanto, un service worker en el directorio raíz de una app controla las solicitudes de todos los archivos de la app.
Cómo mover el service worker
Mueve service-worker.js al directorio below/ y actualiza la URL del trabajador de servicio en el código de registro en index.html.
Cancela el registro del service worker actual en el navegador y actualiza la página.
La consola muestra que el alcance del trabajador de servicio ahora es http://localhost:8081/below/. En Chrome, también puedes ver el alcance del service worker en la pestaña de la aplicación de DevTools:

De vuelta en la página principal, haz clic en Otra página, Otra página y Atrás. ¿Qué solicitudes de recuperación se registran? ¿Cuáles no lo son?
Explicación
El alcance predeterminado del service worker es la ruta de acceso al archivo del service worker. Dado que el archivo del trabajador de servicio ahora está en below/, ese es su alcance. Ahora, la consola solo registra eventos de recuperación para another.html, another.css y another.js, ya que estos son los únicos recursos dentro del alcance del service worker.
Cómo establecer un alcance arbitrario
Vuelve a colocar el trabajador de servicio en el directorio raíz del proyecto (app/) y actualiza la URL del trabajador de servicio en el código de registro en index.html.
Usa la referencia en MDN para establecer el alcance del trabajador de servicio en el directorio below/ con el parámetro opcional en register().
Cancela el registro del service worker y actualiza la página. Haz clic en Otra página, Otra página y Atrás.
Nuevamente, la consola muestra que el alcance del Service Worker ahora es http://localhost:8081/below/ y registra eventos de recuperación solo para another.html, another.css y another.js.
Explicación
Es posible establecer un alcance arbitrario pasando un parámetro adicional al registrarse, por ejemplo:
navigator.serviceWorker.register('/service-worker.js', {
scope: '/kitten/'
});En el ejemplo anterior, el alcance del trabajador de servicio se establece en /kitten/. El service worker intercepta las solicitudes de las páginas en /kitten/ y /kitten/lower/, pero no de páginas como /kitten o /.
Nota: No puedes establecer un alcance arbitrario que esté por encima de la ubicación real del service worker. Sin embargo, si tu service worker está activo en un cliente que se entrega con el encabezado Service-Worker-Allowed, puedes especificar un alcance máximo para ese service worker por encima de la ubicación del service worker.
Más información
Código de solución
Para obtener una copia del código que funciona, navega a la carpeta solution/.
Ahora tienes un service worker simple en funcionamiento y comprendes su ciclo de vida.
Más información
Para ver todos los codelabs del curso de capacitación sobre APW, consulta el codelab de bienvenida del curso.