Prompt y contexto
Tu sitio intercepta solicitudes de navegación con un Service Worker para ofrecer un fallback sin conexión y almacenamiento en caché compartido. La primera navegación espera a que el worker se inicie antes de que comience la solicitud de red. Diseña navigation preload para navegadores no compatibles mientras evitas solicitudes duplicadas, escrituras de caché obsoletas y carreras de respuesta.
Lo que evalúa el entrevistador
Navigation preload es una solicitud de navegación iniciada por el navegador que se ejecuta mientras el Service Worker se inicia; no es ni precaching ni link rel=preload para recursos arbitrarios. Cubre cómo habilitarlo durante activate, leer preloadResponse en fetch, la política de red frente a caché, el encabezado Service-Worker-Navigation-Preload, el fallback por tiempo de espera y errores, y la medición.
Preguntas aclaratorias para hacer primero
Destino de la página y la caché
Aclara si la navegación devuelve HTML renderizado en el servidor (SSR), un shell de SPA o una página sin conexión; qué rutas se pueden almacenar en caché; y si los datos específicos del usuario deben omitir las cachés compartidas. Las respuestas personalizadas no deben escribirse en una caché pública.
Ciclo de vida y compatibilidad del navegador
Confirma el registro, la actualización, el alcance de control y la compatibilidad de los navegadores de destino para navigationPreload. No se puede asumir que una primera navegación no controlada pase a través del worker actual.
Política de red y consistencia
Elige el comportamiento network-first, cache-first o stale-while-revalidate y define la respuesta sin conexión. Decide cómo el servidor lee el encabezado de preload sin alterar accidentalmente las claves de caché.
Estructura de respuesta de 30 segundos
“Detecta la compatibilidad de características y habilita navigation preload en el evento activate del Service Worker. El navegador inicia la solicitud de navegación mientras el worker se inicia; el manejador fetch primero espera a event.preloadResponse, luego verifica la caché o llama a fetch solo cuando no existe una respuesta de preload utilizable. Acepta una respuesta únicamente cuando la URL, la identidad y la política de caché coincidan. Compara compatibilidad, tiempo de inicio, TTFB, aciertos de caché, solicitudes duplicadas y errores de fallback antes y después del despliegue.”
Respuesta detallada paso a paso
Paso 1: Habilitarlo durante activate
Tras verificar registration.navigationPreload, llama a enable() dentro de waitUntil de activate para que la configuración se complete antes de que el nuevo worker se considere listo. setHeaderValue() puede agregar contexto, pero el valor no debe contener estado privado o que no sea almacenable en caché.
Paso 2: Consumir preloadResponse en fetch
Lee event.preloadResponse únicamente para solicitudes de navegación. Puede resolverse en un Response o en undefined. Da prioridad a una respuesta de preload válida; de lo contrario, sigue la política de caché o de fetch ordinaria. No inicies una segunda solicitud de red antes de decidir si la promesa de preload ha producido un resultado utilizable.
Paso 3: Definir los límites de caché e identidad
El HTML de SSR que contiene datos de identidad, geografía o experimentos debe respetar las claves de caché y los encabezados de respuesta existentes. No lo coloques incondicionalmente en Cache Storage. Un shell estático puede ser cache-first; una página personalizada puede ser network-first, probando explícitamente el comportamiento de Cookie, Authorization y Vary.
Paso 4: Manejar el encabezado y el enrutamiento del servidor
El servidor puede inspeccionar Service-Worker-Navigation-Preload para reconocer la solicitud paralela y omitir trabajo costoso o usar una caché dedicada. Los proxies y las CDN necesitan una regla explícita para reenviar, ignorar o aplicar Vary a ese encabezado de modo que no genere un uso compartido de caché entre distintos usuarios.
Paso 5: Manejar carreras, tiempos de espera y errores
Si el preload falla, se agota el tiempo de espera o devuelve un estado inadecuado, recurre a la caché o al fetch ordinario según la política establecida. El cuerpo de un Response suele ser de un solo uso; utiliza clone() cuando se requieran dos consumidores y delimita la cancelación y el tiempo de espera. Intenta mostrar una página sin conexión tras un error de red, pero no ocultes un error real del servidor.
Paso 6: Degradar y actualizar de forma segura
Los navegadores no compatibles continúan con el fetch ordinario del Service Worker; los navegadores sin soporte para Service Worker utilizan la red. Durante las actualizaciones del worker, preserva el protocolo de caché anterior y pospón la eliminación hasta que el nuevo worker esté listo para usarse, evitando interrupciones durante la activación.
Paso 7: Medir el rendimiento real y la corrección
Compara inicios en frío y en caliente, redes lentas, modo sin conexión, primeras visitas no controladas y actualizaciones del worker. Registra el tiempo de navegación a respuesta, TTFB, inicio del worker, aciertos de preload, aciertos de caché, solicitudes duplicadas y errores de fallback. Verifica el aislamiento de identidad y el comportamiento del navegador, no solo el tiempo de carga promedio.
Ejemplo de respuesta de alta calidad
Detectaría las características y habilitaría navigation preload en activate, para luego esperar a preloadResponse primero en el manejador fetch de navegación. Solo cuando esté ausente o no sea adecuado, el manejador recurriría a la caché o al fetch ordinario. La política de caché debe separar los shells estáticos del HTML de SSR personalizado, y el servidor puede utilizar el encabezado de preload sin alterar el aislamiento de caché. Los navegadores no compatibles conservan el comportamiento de fetch ordinario. Probaría inicios en frío, redes lentas, modo sin conexión, visitas no controladas, actualizaciones y conteos de solicitudes duplicadas mientras comparo el TTFB y el tiempo de inicio.
Errores comunes
- Error: Tratar navigation preload como precaching de recursos estáticos. → Por qué falla: Está orientado a la navegación y se ejecuta junto con el inicio del worker. → Solución: Consumir
preloadResponseen el manejador fetch. - Error: Iniciar un fetch incondicional cuando preload no tiene un resultado inmediato. → Por qué falla: Puede duplicar solicitudes y efectos secundarios. → Solución: Definir el orden de la promesa, la caché y el fetch.
- Error: Escribir HTML personalizado en un Cache Storage compartido. → Por qué falla: Se ignoran los límites de Cookie, Authorization o Vary. → Solución: Utilizar una política network-first consciente de la identidad.
- Error: Comparar solo el tiempo de carga promedio. → Por qué falla: Los inicios en frío, las visitas no controladas y las solicitudes duplicadas desaparecen en el promedio. → Solución: Rastrear TTFB, inicio, aciertos y errores por cohorte.
Preguntas de seguimiento y respuestas
Pregunta de seguimiento 1: ¿Por qué no usar link preload directamente?
link rel=preload se declara en la página y está orientado a recursos. Navigation preload es una solicitud del navegador para la navegación que se ejecuta durante el inicio del Service Worker; su ciclo de vida y su API de consumo son diferentes.
Pregunta de seguimiento 2: ¿Por qué preloadResponse puede ser undefined?
Es posible que el navegador no lo admita, que la solicitud no sea una navegación, que el preload esté deshabilitado o que la solicitud de red falle antes del evento del worker. Trata undefined como una bifurcación normal.
Pregunta de seguimiento 3: ¿Cómo se evita leer el cuerpo de un Response dos veces?
El cuerpo de un Response normalmente es de un solo uso. Llama a clone() cuando tanto la página como la caché lo necesiten, y maneja los errores y la cancelación en ambos consumidores.
Pregunta de seguimiento 4: ¿Por qué la primera visita aún podría no mostrar ninguna mejora de velocidad?
Una página no controlada no enruta la navegación a través del worker actual, y el registro, la instalación y la activación toman tiempo. Mide las primeras visitas no controladas por separado en lugar de clasificarlas como fallos de preload.