PWA mínima

Fecha de publicación: 2023-02-27

Cualquier sitio web puede convertirse en una PWA. Como una PWA se basa en HTML, CSS y JavaScript, basta con cumplir unos requisitos mínimos.

Web manifest

Un manifest sencillo incluye descripción, colores, iconos y direcciones:

{
  "background_color": "#000000", "description": "Simple PWA",
  "display": "standalone",
  "icons": [
    {"sizes": "180x180", "src": "./img/favicon-180.png", "type": "image/png"},
    {"sizes": "192x192", "src": "./img/favicon-192.png", "type": "image/png"},
    {"sizes": "512x512", "src": "./img/favicon-512.png", "type": "image/png"}
  ],
  "id": "/", "name": "Simple PWA", "scope": "./",
  "short_name": "Simple PWA", "start_url": "./", "theme_color": "#000000"
}

Iconos

Los iconos representan la aplicación en la pantalla de inicio, la barra de tareas y el selector de aplicaciones. Ofrece varios tamaños, incluidos 192x192 y 512x512 para Android y 180x180 para Apple, en PNG o SVG.

Service Worker

Para instalar la aplicación en el teléfono, el service worker debe proporcionar al menos acceso sin conexión al app shell. No es obligatorio guardar los demás recursos:

'use strict';
const CACHE_STATIC = 'static-cache-v1';
const FILES_TO_CACHE = ['./', './favicon.ico', './img/favicon-512.png', './index.html', './pwa.json'];

function onFetch(evt) {
  async function cacheOrFetch(req) {
    const cache = await self.caches.open(CACHE_STATIC);
    const cached = await cache.match(req);
    return cached ?? await fetch(req);
  }
  evt.respondWith(cacheOrFetch(evt.request));
}
function onInstall(evt) {
  evt.waitUntil(Promise.all(FILES_TO_CACHE.map((url) => caches.open(CACHE_STATIC).then((cache) => cache.add(url)))));
}
self.addEventListener('fetch', onFetch);
self.addEventListener('install', onInstall);

App Shell

El app shell suele ser el archivo principal, index.html. Indica al navegador dónde está el manifest y registra el service worker:

<link rel="manifest" href="./pwa.json">
<script>
if ('serviceWorker' in navigator) {
  self.addEventListener('load', async () => {
    const container = navigator.serviceWorker;
    if (container.controller === null) await container.register('sw.js');
  });
}
</script>

Conclusión

Casi cualquier sitio puede convertirse en una PWA siguiendo estas reglas. Sin embargo, una PWA mínima solo coloca el icono en la pantalla de inicio. Para aprovechar las Web API modernas, la aplicación debe diseñarse desde el principio pensando en funcionamiento offline, almacenamiento local y cálculo en el cliente.

Fragmentos adicionales de código fuente

}, {
}
],
}
const CACHE_STATIC = ‘static-cache-v1’;
const FILES_TO_CACHE = [
]; function onActivate(evt) {
console.log(SW: send 'claim' message to the clients.);
evt.waitUntil(
self.clients.claim()
);
}
function onFetch(evt) {
async function cacheOrFetch(req) {
const cache = await self.caches.open(CACHE_STATIC);
const cachedResponse = await cache.match(req);
return cachedResponse ?? await fetch(req);
}
console.log(SW: fetch '${evt.request}'.);
evt.respondWith(cacheOrFetch(evt.request));
}
function onInstall(evt) {
async function cacheStaticFiles() {
const cacheStat = await caches.open(CACHE_STATIC);
await Promise.all(
FILES_TO_CACHE.map(function (url) {
return cacheStat.add(url).catch(function (reason) {
console.log('${url}' failed: ${String(reason)});
});
})
);
}
console.log(SW: cache app shell on install.);
evt.waitUntil(cacheStaticFiles());
}
self.addEventListener(‘activate’, onActivate);
self.addEventListener(‘fetch’, onFetch);
self.addEventListener(‘install’, onInstall);

Los Service Workers y la autonomía de una PWA muestran cómo el navegador sostiene el comportamiento de una aplicación entre ejecuciones. La visión más amplia aparece en El navegador como sistema operativo para desarrollar aplicaciones modernas.