Cómo controlar las solicitudes de navegación

Responde a las solicitudes de navegación sin esperar en la red mediante un service worker.

Las solicitudes de navegación son solicitudes de documentos HTML que realiza tu navegador cada vez que ingresas una nueva URL en la barra de navegación o sigues un vínculo en una página que te lleva a una nueva URL. Aquí es donde los service worker tienen el mayor impacto en el rendimiento: si utilizas un service worker para responder a las solicitudes de navegación sin esperar a que llegue la red, puedes asegurarte de que las navegaciones sean rápidas de forma confiable, además de ser resilientes cuando la red no esté disponible. Esta es la mayor victoria de rendimiento que proviene de un service worker, en comparación con lo que se puede lograr con el almacenamiento en caché de HTTP.

Como se detalla en la guía Cómo identificar recursos cargados desde la red, una solicitud de navegación es la primera de potencialmente muchas solicitudes que se hacen en la "cascada" del tráfico de red. El código HTML que cargas a través de una solicitud de navegación inicia el flujo de todas las demás solicitudes de subrecursos como imágenes, secuencias de comandos y estilos.

Dentro del controlador de eventos fetch de un service worker, puedes verificar la propiedad request.mode en FetchEvent para determinar si una solicitud es una navegación. Si se configuró como 'navigate', es una solicitud de navegación.

Como regla general, no uses Cache-Control headers de larga duración para almacenar en caché la respuesta HTML de una solicitud de navegación. Por lo general, deberían satisfacerse a través de la red, con Cache-Control: no-cache, para garantizar que el HTML, junto con la cadena de solicitudes de red posteriores, se actualicen (razonablemente) Lamentablemente, competir a la red cada vez que el usuario navega a una página nueva significa que cada navegación podría ser lenta. Como mínimo, significa que no será rápida confiablemente.

Diferentes enfoques para las arquitecturas

Comprender cómo responder a las solicitudes de navegación mientras se evita la red puede ser complicado. El enfoque correcto depende en gran medida de la arquitectura del sitio web y la cantidad de URLs únicas a las que los usuarios pueden navegar.

Si bien no existe una solución única para todos los casos, los siguientes lineamientos generales deberían ayudarte a decidir qué enfoque es el más viable.

Sitios estáticos pequeños

Si tu app web consta de una cantidad relativamente pequeña (por ejemplo, un par de docenas) de URLs únicas, y cada una de esas URLs corresponde a un archivo HTML estático diferente, un enfoque viable es almacenar en caché todos esos archivos HTML y responder a las solicitudes de navegación con el código HTML almacenado en caché adecuado.

Con el almacenamiento previo en caché, puedes almacenar el HTML en caché por adelantado, apenas se instale el service worker, y actualizar el HTML almacenado en caché cada vez que vuelvas a compilar el sitio y vuelvas a implementar el service worker.

Como alternativa, si prefieres evitar el almacenamiento previo en caché de todo tu código HTML, quizás porque los usuarios tienden a navegar solo a un subconjunto de URLs en tu sitio, puedes usar una estrategia de almacenamiento en caché del entorno de ejecución inactivo al momento de volver a validar. Sin embargo, debes tener cuidado con este enfoque, ya que cada documento HTML individual se almacena en caché y se actualiza por separado. El uso del almacenamiento en caché en tiempo de ejecución para HTML es el más adecuado si tienes una pequeña cantidad de URLs que el mismo conjunto de usuarios vuelve a visitar con frecuencia y si estás de acuerdo con que esas URLs se revaliden de forma independiente unas de otras.

Apps de una sola página

Las aplicaciones web modernas suelen usar la arquitectura de una sola página. En él, JavaScript del cliente modifica el HTML en respuesta a las acciones del usuario. Este modelo usa la API de History para modificar la URL actual a medida que el usuario interactúa con la app web, lo que da como resultado una navegación "simulada". Si bien las navegaciones posteriores pueden ser "falsas", la navegación inicial es real, y es importante asegurarse de que no esté bloqueada en la red.

Afortunadamente, si usas la arquitectura de una sola página, debes seguir un patrón sencillo para entregar la navegación inicial desde la caché: el shell de la aplicación. En este modelo, el service worker responde a las solicitudes de navegación con la devolución del mismo archivo HTML único que ya se almacenó en caché, sin importar la URL que se solicite. Este código HTML debe ser básico y contener, quizás, un indicador de carga genérico o un contenido básico. Una vez que el navegador carga este HTML desde la caché, el código JavaScript existente del cliente toma el control y renderiza el contenido HTML correcto para la URL de la solicitud de navegación original.

Workbox proporciona las herramientas que necesitas para implementar este enfoque. navigateFallback option te permite especificar qué documento HTML usar como shell de la app, junto con una lista opcional de permisos y denegación para limitar este comportamiento a un subconjunto de las URLs.

Apps de varias páginas

Si tu servidor web genera el código HTML de tu sitio de forma dinámica, o si tienes más de unas decenas de páginas únicas, es mucho más difícil evitar la red cuando se administran las solicitudes de navegación. Es probable que los consejos que se indican en Todo lo demás se apliquen a tu caso.

Sin embargo, para un subconjunto determinado de apps de varias páginas, es posible que puedas implementar un service worker que replique por completo la lógica utilizada en tu servidor web para generar HTML. Esto funciona mejor si puedes compartir información de enrutamiento y plantillas entre los entornos de servidor y service worker y, en particular, si tu servidor web usa JavaScript (sin depender de funciones específicas de Node.js, como el acceso al sistema de archivos).

Si tu servidor web pertenece a esa categoría y deseas explorar un enfoque para mover la generación HTML fuera de la red y hacia tu service worker, la guía en Más allá de las SPA: arquitecturas alternativas para tu AWP puede ayudarte a comenzar.

Todas las demás

Si no puedes responder las solicitudes de navegación con HTML en caché, debes tomar medidas para asegurarte de que agregar un service worker a tu sitio (para controlar otras solicitudes que no sean de HTML) no ralentice la navegación. Si inicias el service worker sin usarlo para responder a una solicitud de navegación, se generará una pequeña latencia (como se explica en Compila apps más rápidas y resilientes con Service Worker). Para mitigar esta sobrecarga, puedes habilitar una función llamada precarga de navegación y, luego, usar la respuesta de red que se cargó previamente dentro del controlador de eventos fetch.

Workbox proporciona una biblioteca auxiliar que detecta si se admite la precarga de navegación y, de ser así, simplifica el proceso de indicarle a tu service worker que use la respuesta de red.

Foto de Aaron Burden en Unsplash