PWA mínima
Fecha de publicación: 2023-02-27Cualquier sitio web puede convertirse en una PWA. Como una PWA se basa en HTML, CSS y JavaScript, basta con cumplir unos requisitos mínimos.
- HTTPS: el sitio debe usar HTTPS.
- Web manifest: aporta al navegador los metadatos de la PWA.
- Icono: permite mostrar la aplicación en la pantalla de inicio.
- Service Worker: procesa solicitudes y puede responder sin conexión.
- App Shell: el HTML que instala e inicia la PWA.
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.