Carga previa de Navigation para HTML centrado en la red

Cuando un service worker controla eventos fetch, el navegador espera a que el service worker proporcione una respuesta. Si bien la latencia de la solicitud de red es una parte importante de la espera, es posible que el navegador también deba esperar a que el service worker se inicie y active las devoluciones de llamada de eventos fetch.

El tiempo de inicio varía según el dispositivo y sus capacidades, pero el tiempo requerido puede ser considerable; a veces, hasta medio segundo cuando una CPU es lenta o está funcionando en un estado limitado debido a las condiciones ambientales. Es probable que la mejora del rendimiento de evitar la red supere este tiempo de inicio cuando tus respuestas de navegación se entregan desde una instancia de Cache. Para las solicitudes de navegación que van a la red, introducir un service worker puede crear un retraso perceptible.

Ingresar a la precarga de navegación

La precarga de Navigation es una función de service worker que resuelve el retraso que genera el tiempo de inicio del service worker. Si la precarga de navegación no está habilitada, el inicio del service worker y la solicitud de navegación que controla se producirán consecutivamente:

Una barra amarilla y azul, con dos segmentos que muestran acciones consecutivas. El primer segmento, en amarillo, dice "SW boot" y un segmento azul que dice "Navigation request".

Esto no es lo ideal, pero puedes corregirlo habilitando la precarga de navegación, que garantiza que el inicio del service worker y la solicitud de navegación se producen simultáneamente:

Dos barras apiladas una sobre otra y alineadas a la izquierda, que representan dos acciones simultáneas. La barra amarilla está etiquetada como “SW boot” y la azul, “Navigation request”.

Si bien la precarga de navegación es una excelente optimización del rendimiento de los sitios que usan service workers, no es una función que debas habilitar en todas las situaciones. En particular, los sitios que usan un shell de app almacenado previamente en caché no necesitan precarga de navegación, ya que la caché entrega la solicitud de navegación para el lenguaje de marcado de shell de app sin latencia de navegación. En estos casos, la respuesta precargada se desperdiciará, lo cual no es bueno.

El mejor momento para usar la precarga de navegación es cuando un sitio web no puede almacenar previamente en caché HTML. Piensa en sitios web en los que las respuestas de lenguaje de marcado son dinámicas y varían con aspectos como el estado de autenticación. Las solicitudes de navegación pueden usar una estrategia centrada en la red (o incluso solo en la red), y ahí es donde la precarga de navegación puede marcar una gran diferencia.

Usa la precarga de navegación en Workbox

Es complicado usar la precarga de navegación directamente en un service worker que no funciona con Workbox. En primer lugar, no es compatible con todos los navegadores. En segundo lugar, puede ser difícil hacerlo bien. Puedes aprender a usarlo directamente en esta excelente explicación de Jake Archibald.

Workbox simplifica el uso de la precarga de navegación, ya que el método enable del módulo workbox-navigation-preload realiza las verificaciones de compatibilidad de funciones necesarias y crea el objeto de escucha de eventos activate para habilitarlo.

A partir de aquí, los beneficios de la precarga de navegación se materializan en la compatibilidad con navegadores usando Workbox para manejar las solicitudes de navegación con un controlador de estrategia centrado en la red:

import * as navigationPreload from 'workbox-navigation-preload';
import {NetworkFirst, StaleWhileRevalidate} from 'workbox-strategies';
import {registerRoute, NavigationRoute, Route} from 'workbox-routing';
import {precacheAndRoute} from 'workbox-precaching';

// Precache the manifest
precacheAndRoute(self.__WB_MANIFEST);

// Enable navigation preload
navigationPreload.enable();

// Create a new navigation route that uses the Network-first, falling back to
// cache strategy for navigation requests with its own cache. This route will be
// handled by navigation preload. The NetworkOnly strategy will work as well.
const navigationRoute = new NavigationRoute(new NetworkFirst({
  cacheName: 'navigations'
}));

// Register the navigation route
registerRoute(navigationRoute);

// Create a route for image, script, or style requests that use a
// stale-while-revalidate strategy. This route will be unaffected
// by navigation preload.
const staticAssetsRoute = new Route(({request}) => {
  return ['image', 'script', 'style'].includes(request.destination);
}, new StaleWhileRevalidate({
  cacheName: 'static-assets'
}));

// Register the route handling static assets
registerRoute(staticAssetsRoute);

Cuando la precarga de navegación esté habilitada, Workbox responderá a las solicitudes de navegación que usan las estrategias NetworkFirst o NetworkOnly con la respuesta precargada.

¿Cómo puedo saber si la precarga de navegación está funcionando?

En las compilaciones de desarrollo, Workbox registra mucho acerca de lo que hace. Si deseas verificar si la precarga de navegación funciona en Workbox, abre la consola en un navegador compatible durante una solicitud de navegación y verás un mensaje de registro que dice lo siguiente:

Captura de pantalla de los registros de Workbox en la consola de Herramientas para desarrolladores de Chrome. Los mensajes se leen, de arriba abajo: "El router responde a /", "Usando una solicitud de navegación precargada para /" y "Usa NetworkFirst para responder a /".

Este registro no será visible en las compilaciones de producción de forma predeterminada, por lo que no lo verás cuando implementes tu service worker en producción, pero es una excelente manera de verificar que la precarga de navegación esté funcionando (entre otras cosas).

Personaliza las respuestas precargadas

Cuando se usa la precarga de navegación, puede haber situaciones en las que sea necesario personalizar las respuestas precargadas en el backend de una aplicación. Los service workers que transmiten contenido parcial desde la red son una situación en la que esto puede ser útil.

En casos como estos, es bueno saber que las solicitudes de precarga se envían con un encabezado Service-Worker-Navigation-Preload configurado con un valor predeterminado de true:

Service-Worker-Navigation-Preload: true

Luego, en el backend de la aplicación que elijas, puedes verificar este encabezado y modificar la respuesta para que se adapte a tus necesidades. Si el valor predeterminado del encabezado presenta problemas por algún motivo, puedes cambiarlo en el contexto de la ventana. Solo debes saber que el trabajo que realices en el servidor para leer este encabezado depende de ti y está fuera del alcance de Workbox.

Conclusión

Es difícil hacer correctamente la precarga de navegación cuando se usa directamente, pero ese trabajo arduo vale la pena para garantizar que un service worker no impida que el navegador realice solicitudes de navegación. Gracias a Workbox, puedes beneficiarte de la precarga de navegación con mucho menos trabajo. Para obtener más detalles sobre el módulo workbox-navigation-preload, consulta su documentación de referencia.