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 gran parte de la espera, es posible que el navegador también tenga que esperar a que el service worker se inicie y active 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 ganancia de rendimiento de evitar la red supere este tiempo de inicio cuando tus respuestas de navegación se entregan desde una instancia de Cache. En el caso de las solicitudes de navegación que van a la red, introducir un service worker puede crear un retraso perceptible.

Ingresar la precarga de navegación

La precarga de navegación es una función de service worker que soluciona el retraso causado por el tiempo de inicio del service worker. Sin la precarga de navegación habilitada, tanto el inicio del service worker como la solicitud de navegación que controla ocurrirán de forma consecutiva:

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 ideal, pero puedes solucionarlo habilitando la precarga de navegación, que garantiza que el inicio del service worker y la solicitud de navegación ocurran de forma simultánea:

Dos barras apiladas una sobre otra y alineadas a la izquierda, que representan dos acciones simultáneas. La barra amarilla está etiquetada como 'inicio del SW' y la barra azul está etiquetada 'Solicitud de navegación'.

Si bien la precarga de navegación es una excelente optimización del rendimiento para 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 previamente almacenado 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 ninguna latencia de navegación. En estos casos, la respuesta precargada será desperdiciada, lo cual no es bueno.

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

Usa la precarga de navegación en Workbox

Usar la precarga de la navegación directamente en un service worker que no funciona con Workbox es complicado. 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.

El cuadro de trabajo 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 por ti.

A partir de aquí, los beneficios de la precarga de navegación se alcanzan en la compatibilidad con navegadores mediante Workbox para manejar las solicitudes de navegación con un controlador de estrategias 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 funciona la precarga de navegación?

En las compilaciones de desarrollo, Workbox registra mucho lo que hace. Si deseas verificar si la carga previa de la 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 /", "Uso de una solicitud de navegación precargada para /" y "Uso de 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 funcione (entre otras cosas).

Cómo personalizar 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 de las situaciones en las que esto podría ser útil.

En casos como estos, vale la pena saber que las solicitudes de precarga se envían con un encabezado Service-Worker-Navigation-Preload establecido con un valor predeterminado de true:

Service-Worker-Navigation-Preload: true

Luego, en el backend de tu 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 es problemático por algún motivo, puedes cambiarlo en el contexto de la ventana. Ten en cuenta que cualquier 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 lograr la carga previa de la navegación correcta 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.