En ciertas situaciones, es posible que quieras que una respuesta de resguardo esté almacenada en caché en caso de que el usuario esté sin conexión. La implementación de un resguardo es una alternativa a los comportamientos de almacenamiento en caché que proporcionan las estrategias como "priorizar la red" o "caer en la revalidación".
Un resguardo es una respuesta genérica única que se adapta a todos y constituye un mejor marcador de posición que el que el navegador proporcionaría de forma predeterminada cuando falla una solicitud. Por ejemplo:
- Una alternativa a la "imagen faltante" marcador de posición.
- Una alternativa HTML al estándar "no hay conexión de red disponible" .
Página sin conexión únicamente
Si solo necesitas proporcionar una página HTML sin conexión personalizada, pero nada más, aquí te mostramos una receta de referencia que puedes seguir:
import {offlineFallback} from 'workbox-recipes';
import {setDefaultHandler} from 'workbox-routing';
import {NetworkOnly} from 'workbox-strategies';
setDefaultHandler(new NetworkOnly());
offlineFallback();
El código anterior usa setDefaultHandler
para emplear una estrategia solo de red de forma predeterminada para todas las rutas. Luego, ejecuta la receta offlineFallback
para entregar el resguardo sin conexión en caso de que se produzca un error. La receta supone que tu archivo HTML de resguardo sin conexión tendrá el nombre offline.html
y se entregará desde la raíz de tu servidor web.
Resguardos integrales
Cuando se produce una falla de red o un error de caché, las estrategias de almacenamiento en caché que ofrece workbox-strategies
se rechazan de forma constante. Esto promueve el patrón de establecer una “captura” global para lidiar con cualquier falla en una sola función de controlador, lo que te permite ofrecer diferentes resguardos para diferentes valores request.destination
.
En el siguiente ejemplo, se usa la receta warmStrategyCache
de workbox-recipes
y se configura un controlador de captura para entregar elementos almacenados en caché con anticipación en la caché del entorno de ejecución. Sin embargo, el almacenamiento previo en caché puede ser una mejor opción para tu aplicación:
import {warmStrategyCache} from 'workbox-recipes';
import {setDefaultHandler, setCatchHandler} from 'workbox-routing';
import {CacheFirst, StaleWhileRevalidate} from 'workbox-strategies';
// Fallback assets to cache
const FALLBACK_HTML_URL = '/offline.html';
const FALLBACK_IMAGE_URL = '/images/image-not-found.jpg';
const FALLBACK_STRATEGY = new CacheFirst();
// Warm the runtime cache with a list of asset URLs
warmStrategyCache({
urls: [FALLBACK_HTML_URL, FALLBACK_IMAGE_URL],
strategy: FALLBACK_STRATEGY,
});
// Use a stale-while-revalidate strategy to handle requests by default.
setDefaultHandler(new StaleWhileRevalidate());
// This "catch" handler is triggered when any of the other routes fail to
// generate a response.
setCatchHandler(async ({request}) => {
// The warmStrategyCache recipe is used to add the fallback assets ahead of
// time to the runtime cache, and are served in the event of an error below.
// Use `event`, `request`, and `url` to figure out how to respond, or
// use request.destination to match requests for specific resource types.
switch (request.destination) {
case 'document':
return FALLBACK_STRATEGY.handle({event, request: FALLBACK_HTML_URL});
case 'image':
return FALLBACK_STRATEGY.handle({event, request: FALLBACK_IMAGE_URL});
default:
// If we don't have a fallback, return an error response.
return Response.error();
}
});
A continuación, las respuestas de resguardo se almacenan previamente en caché a través de injectManifest
con las herramientas de compilación de Workbox y se entregan como resguardo en caso de que se produzca un error con el método matchPrecache
.
import {matchPrecache, precacheAndRoute} from 'workbox-precaching';
import {setDefaultHandler, setCatchHandler} from 'workbox-routing';
import {StaleWhileRevalidate} from 'workbox-strategies';
// Optional: use the injectManifest mode of one of the Workbox
// build tools to precache a list of URLs, including fallbacks.
precacheAndRoute(self.__WB_MANIFEST);
// Use a stale-while-revalidate strategy to handle requests by default.
setDefaultHandler(new StaleWhileRevalidate());
// This "catch" handler is triggered when any of the other routes fail to
// generate a response.
setCatchHandler(async ({request}) => {
// Fallback assets are precached when the service worker is installed, and are
// served in the event of an error below. Use `event`, `request`, and `url` to
// figure out how to respond, or use request.destination to match requests for
// specific resource types.
switch (request.destination) {
case 'document':
// FALLBACK_HTML_URL must be defined as a precached URL for this to work:
return matchPrecache(FALLBACK_HTML_URL);
case 'image':
// FALLBACK_IMAGE_URL must be defined as a precached URL for this to work:
return matchPrecache(FALLBACK_IMAGE_URL);
default:
// If we don't have a fallback, return an error response.
return Response.error();
}
});
Un ejemplo de caso de uso para la segunda configuración de resguardo es si una página se almacenó en caché con anticipación, pero no se almacenaron las imágenes (u otros recursos) solicitadas por la página. La página aún se puede leer desde la caché cuando el usuario está sin conexión, pero se pueden proporcionar marcadores de posición de resguardo o funcionalidades alternativas si se produce un error de red.
Calienta la caché del entorno de ejecución
Workbox mantiene cachés separadas para el almacenamiento previo en caché y las cachés de entorno de ejecución, y puede haber situaciones en las que quieras almacenar en caché con anticipación sin depender del almacenamiento previo en caché, ya que las actualizaciones del manifiesto de almacenamiento previo en caché requerirán que implementes un service worker actualizado.
Para preparar la caché del tiempo de ejecución con recursos de forma anticipada, puedes usar la receta warmStrategyCache
de workbox-recipes
. De forma interna, esta estrategia llama a Cache.addAll
en el evento install
de un service worker.
import {warmStrategyCache} from 'workbox-recipes';
import {CacheFirst} from 'workbox-strategies';
// This can be any strategy, CacheFirst used as an example.
const strategy = new CacheFirst();
const urls = [
'/offline.html',
];
warmStrategyCache({urls, strategy});
Conclusión
Administrar las respuestas de resguardo para solicitudes fallidas lleva un poco de trabajo, pero con un poco de planificación anticipada, puedes configurar tu aplicación web para proporcionar cierto nivel de contenido y funcionalidad cuando el usuario no tiene conexión.