Offline & Installable

PWA & Service Workers

Una Progressive Web App se instala como una aplicación nativa, funciona sin conexión y carga instantáneamente en visitas recurrentes. Los service workers y un web manifest hacen que esto sea posible.

advanced14 min readUpdated 15 sept 2026
sw.js
js
// sw.js
const CACHE = "app-v1";
const ASSETS = ["/", "/app.js", "/styles.css"];

self.addEventListener("install", (event) => {
  event.waitUntil(
    caches.open(CACHE).then((cache) => cache.addAll(ASSETS)),
  );
});

self.addEventListener("fetch", (event) => {
  event.respondWith(
    caches.match(event.request).then((cached) => cached || fetch(event.request)),
  );
});
Requiere
HTTPS o localhost
Manifest
manifest.webmanifest
Worker
service worker
Caching
Cache Storage API
Instalación
Añadir a pantalla de inicio
Beneficio clave
Modo offline y repeticiones instantáneas

Por que importa

Por qué crear una PWA

Funciona sin conexión

Un service worker sirve assets y datos almacenados en caché, por lo que la aplicación sigue funcionando cuando se pierde la red.

Visitas recurrentes instantáneas

Los assets en caché se cargan inmediatamente, convirtiendo una primera visita lenta en una segunda visita instantánea.

Instalable

Con un manifest y un worker, los navegadores ofrecen instalar la aplicación en la pantalla de inicio o en el escritorio.

La imagen completa

Las tres partes de una PWA

Un manifest que describe la aplicación, un service worker que controla la red y un origen seguro que hace que ambos sean posibles.

El manifest

Describir

El nombre, los iconos, los colores y el modo de visualización indican a la plataforma cómo presentar la aplicación.

El service worker

Interceptar

Un script en segundo plano que se sitúa entre la página y la red, controlando las solicitudes.

La caché

Almacenar

La Cache Storage API guarda respuestas que el worker puede servir más tarde.

PWA de un vistazo

El núcleo de una PWA

Web manifest

Metadatos que hacen que la aplicación sea instalable y controlan su apariencia.

Service worker

Un script que intercepta eventos fetch y gestiona las cachés.

Cache Storage

Un almacén de clave-valor para pares de solicitud y respuesta.

Estrategia de caching

Cache-first, network-first, stale-while-revalidate y más.

Offline fallback

Una página o estado que se muestra cuando nada está en caché y la red no está disponible.

Background sync

Reintenta las solicitudes fallidas cuando se recupera la conectividad.

Una breve historia

De hacks offline a aplicaciones web instalables

  1. 2014

    Propuesta de service workers

    Un nuevo tipo de worker otorga a las páginas una capa de red programable.

    14
  2. 2015

    Progressive Web Apps

    Se acuña el término para describir experiencias web instalables y capaces de funcionar offline.

    15
  3. 2018

    Soporte amplio en navegadores

    Los service workers y los avisos de instalación llegan a todos los navegadores principales.

    18
  4. 2020

    Madurez de Workbox

    La librería Workbox de Google hace que las estrategias de caching sean más fáciles de implementar de forma segura.

    20
  5. Hoy

    Mainstream

    Muchos sitios importantes implementan un service worker para soporte offline y velocidad.

    Hoy

La guia completa

PWA & Service Workers: Todo lo que necesitas saber

¿Qué es una PWA?

Una Progressive Web App es un sitio web que se comporta como una aplicación instalada: funciona sin conexión, carga instantáneamente en visitas recurrentes y puede añadirse a la pantalla de inicio o al escritorio. No existe una única tecnología llamada PWA; se trata de un conjunto de capacidades que se adoptan de forma incremental.

Tres ingredientes hacen que funcione:

  1. HTTPS, para que el navegador confíe lo suficiente en tu origen como para permitir un service worker.
  2. Un web manifest que describe el nombre, los iconos y el modo de visualización de la aplicación.
  3. Un service worker, un script en segundo plano que intercepta las solicitudes de red y gestiona las cachés.

El resultado es una experiencia que se siente nativa, pero que sigue siendo un sitio web que puedes actualizar al instante.

El manifiesto web

El manifiesto es un archivo JSON vinculado desde el head del HTML. Le indica a la plataforma cómo presentar la aplicación una vez instalada.

{
  "name": "hackweb Reader",
  "short_name": "Reader",
  "start_url": "/",
  "display": "standalone",
  "background_color": "#0b0d0c",
  "theme_color": "#0b0d0c",
  "icons": [
    { "src": "/icons/192.png", "sizes": "192x192", "type": "image/png" },
    { "src": "/icons/512.png", "sizes": "512x512", "type": "image/png" }
  ]
}
<!-- index.html -->
<link rel="manifest" href="/manifest.webmanifest" />
<meta name="theme-color" content="#0b0d0c" />

display: "standalone" oculta la interfaz del navegador (browser chrome) al estar instalada, mientras que los iconos y colores controlan la pantalla de inicio (splash screen) y el selector de tareas. Un manifiesto válido junto con un service worker es lo que hace que el navegador ofrezca instalar la aplicación.

El ciclo de vida del service worker

Un service worker es un script independiente que no tiene acceso al DOM. Posee un ciclo de vida propio: install, activate y fetch.

// register.js
if ("serviceWorker" in navigator) {
  window.addEventListener("load", () => {
    navigator.serviceWorker.register("/sw.js");
  });
}

Durante el install, realizas el pre-cacheo del app shell. Durante el activate, limpias los caches antiguos. Durante el fetch, interceptas las solicitudes y decides cómo responder. Un nuevo worker espera hasta que todas las páginas que utilizan el anterior se cierren antes de activarse, razón por la cual las actualizaciones a veces requieren una segunda recarga.

Estrategias de almacenamiento en caché

El núcleo de un service worker es su estrategia de almacenamiento en caché. Diferentes recursos requieren un tratamiento distinto.

  • Cache-first — sirve desde la caché y, si falla, recurre a la red. Ideal para activos versionados e inmutables, como bundles con hash.
  • Network-first — intenta obtener el recurso de la red y, si falla, recurre a la caché. Recomendado para HTML y datos que deben estar actualizados.
  • Stale-while-revalidate — sirve la versión almacenada en caché inmediatamente y la actualiza en segundo plano. Excelente para datos donde es aceptable que la información esté ligeramente desactualizada.
  • Cache-only y network-only — para casos de uso muy específicos.
// strategies.js
self.addEventListener("fetch", (event) => {
  const { request } = event;
  if (request.destination === "image") {
    event.respondWith(
      caches.match(request).then((cached) => cached || fetch(request)),
    );
  }
});

La propiedad request.destination te indica qué tipo de recurso se está solicitando, lo que te permite aplicar una estrategia según el tipo de activo.

Fallback offline

Incluso con el uso de caché, algunas solicitudes fallarán. Proporciona un fallback adecuado.

// fallback.js
self.addEventListener("fetch", (event) => {
  if (event.request.mode === "navigate") {
    event.respondWith(
      fetch(event.request).catch(() => caches.match("/offline.html")),
    );
  }
});

Una página de estado offline, un shell en caché o un estado claro de “estás offline” es mucho mejor que el error predeterminado del navegador. Combinado con background sync, las solicitudes que fallaron mientras no había conexión pueden reintentarse automáticamente cuando se recupere la conectividad.

Actualizaciones y versionado

El almacenamiento en caché es potente, pero es fácil cometer errores. La regla es sencilla: asigna versiones a tus cachés y elimina las antiguas al activar. De lo contrario, los usuarios podrían quedar atrapados con archivos obsoletos indefinidamente.

// activate.js
const CACHE = "app-v2";

self.addEventListener("activate", (event) => {
  event.waitUntil(
    caches.keys().then((keys) =>
      Promise.all(keys.filter((k) => k !== CACHE).map((k) => caches.delete(k))),
    ),
  );
});

Para cualquier cosa que vaya más allá de lo básico, la librería Workbox gestiona el precaching, el enrutamiento, la expiración y la limpieza con valores predeterminados probados, y se integra con la mayoría de las herramientas de construcción.

Más allá del modo offline

Los service workers permiten hacer mucho más que el almacenamiento en caché:

  • Background sync: reintenta las solicitudes fallidas cuando se recupera la conexión de red.
  • Push notifications: entrega mensajes incluso cuando la aplicación está cerrada.
  • Periodic sync: actualiza el contenido en segundo plano.
  • Share target: permite que tu aplicación reciba contenido compartido desde el SO.

Cada una de estas funciones requiere el permiso del usuario y debe utilizarse con moderación, pero son precisamente las que hacen que una PWA se sienta como una aplicación de primer nivel.

Mejores prácticas

  • Sirve el contenido a través de HTTPS y registra el worker después de la carga.
  • Versiona las cachés y elimina las antiguas durante el evento activate.
  • Utiliza una estrategia cache-first para assets con hash y network-first para HTML.
  • Proporciona siempre un fallback para el modo offline.
  • Haz precache únicamente del app shell, no de todo el sitio.
  • Considera usar Workbox en lugar de escribir estrategias complejas a mano.
  • Prueba el modo offline y las actualizaciones antes de desplegar a producción.

Errores comunes

  • Cachear HTML indefinidamente y servir páginas obsoletas.
  • Olvidar limpiar los caches antiguos después de un deploy.
  • Cachear respuestas cross-origin opacas sin comprender sus limitaciones.
  • Hacer precaching de todo y saturar la primera instalación.
  • Asumir que el nuevo worker se activa inmediatamente.
  • Ignorar la cuota de almacenamiento y permitir que los caches crezcan sin límite.

Próximos pasos

Un service worker es la mejora de rendimiento más significativa para las visitas recurrentes y la base del soporte offline. Combínalo con las técnicas de la guía de Web Performance, comprende las solicitudes HTTP que intercepta y sirve la aplicación desde un backend en Node.js. Después, añade un manifest y un worker sencillo con estrategia cache-first a un sitio existente y comprueba cómo funciona sin conexión.

Eligiendo una estrategia de caching

Cache-first es rápido y apto para offline en assets versionados. Network-first es ideal para contenido que debe estar actualizado.

Cache-first
// hashed assets never change
self.addEventListener("fetch", (event) => {
  event.respondWith(
    caches.match(event.request).then(
      (cached) => cached || fetch(event.request),
    ),
  );
});
Network-first
// for HTML or fresh data:
// try the network, fall back
event.respondWith(
  fetch(event.request).catch(() =>
    caches.match(event.request),
  ),
);

Actualización de assets en caché

Cambia el nombre de la caché en cada despliegue y elimina las cachés antiguas para que los usuarios no se queden con archivos obsoletos.

Preferible
const CACHE = "app-v2";

self.addEventListener("activate", (event) => {
  event.waitUntil(
    caches.keys().then((keys) =>
      Promise.all(
        keys
          .filter((k) => k !== CACHE)
          .map((k) => caches.delete(k)),
      ),
    ),
  );
});
Evitar
// same cache name forever,
// old files never replaced

Preguntas frecuentes

Preguntas frecuentes

Keep learning

Related topics from the roadmap.

$ comienza a aprender

Listo para aprender PWA & Service Workers?

Nuestro tutorial interactivo te guia a traves de PWA & Service Workers paso a paso — con quizzes y codigo real que puedes ejecutar en el navegador.