Dos formas de precarga: etiquetas <link> y encabezados HTTP

Demián Rezulli
Demián Renzulli

En este codelab, implementarás la carga previa de dos maneras: con <link rel="prefetch"> y con encabezado HTTP Link.

La aplicación de muestra es un sitio web que tiene una página de destino promocional con un descuento especial para la camiseta más vendida de la tienda. Dado que la página de destino se vincula a un solo producto, podemos suponer que un alto porcentaje de usuarios navegará a la página de detalles del producto. Esto hace que la página del producto sea una gran opción para realizar cargas previas en la página de destino.

Cómo medir el rendimiento

Primero, establece el rendimiento de referencia:

  1. Haz clic en Remix to Edit para que el proyecto sea editable.
  2. Para obtener una vista previa del sitio, presiona Ver app. Luego, presiona Pantalla completa pantalla completa.
  3. Presiona "Control + Mayús + J" (o bien "Comando + Opción + J" en Mac) para abrir Herramientas para desarrolladores.
  4. Haga clic en la pestaña Red.

  5. En la lista desplegable Regulación, selecciona 3G rápida para simular un tipo de conexión lenta.

  6. Para cargar la página del producto, haz clic en Comprar ahora en la app de muestra.

La página product-details.html tarda alrededor de 600 ms en cargarse:

Panel Network que muestra los tiempos de carga de product-details.html

Para mejorar la navegación, inserta una etiqueta prefetch en la página de destino para cargar previamente la página product-details.html:

  • Agrega el siguiente elemento <link> al encabezado del archivo views/index.html:
<!doctype html>
  <html>
    <head>
       <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet">

      <link rel="prefetch" href="/product-details.html" as="document">
      ...
</head>

El atributo as es opcional, pero recomendado, ya que ayuda al navegador a establecer los encabezados correctos y determinar si el recurso ya está en la caché. Algunos ejemplos de valores para este atributo son los siguientes: document, script, style, font, image y otros.

Para verificar que funcione la carga previa, haz lo siguiente:

  1. Para obtener una vista previa del sitio, presiona Ver app. Luego, presiona Pantalla completa pantalla completa.
  2. Presiona "Control + Mayús + J" (o bien "Comando + Opción + J" en Mac) para abrir Herramientas para desarrolladores.
  3. Haga clic en la pestaña Red.

  4. En la lista desplegable Regulación, selecciona 3G rápida para simular un tipo de conexión lenta.

  5. Desmarca la casilla de verificación Inhabilitar la caché.

  6. Vuelve a cargar la app.

Ahora, cuando se carga la página de destino, también se carga la página product-details.html, pero con la prioridad más baja:

Panel Network que muestra product-details.html con carga previa.

La página se conserva en la caché HTTP durante cinco minutos. Después de ese período, se aplican las reglas Cache-Control normales del documento. En este caso, product-details.html tiene un encabezado cache-control con un valor de public, max-age=0, lo que significa que la página se conserva durante un total de cinco minutos.

Reevalúa el rendimiento

  1. Vuelve a cargar la app.
  2. Para cargar la página del producto, haz clic en Comprar ahora en la app de muestra.

Observa el panel Red. Existen dos diferencias con el seguimiento de red inicial:

  • La columna Tamaño muestra "caché de carga previa", lo que significa que este recurso se recuperó de la caché del navegador en lugar de la red.
  • En la columna Tiempo, se muestra que el documento tarda cerca de 10 ms en cargarse.

Esto equivale a una reducción de aproximadamente el 98% en comparación con la versión anterior, que tardó cerca de 600 ms.

Panel Network que muestra product-details.html recuperado de la caché de carga previa.

Crédito adicional: Usa prefetch como una mejora progresiva

La carga previa se implementa mejor como una mejora progresiva para los usuarios que navegan con conexiones rápidas. Puedes usar la API de Network Information para verificar las condiciones de la red y basarse en eso para insertar de forma dinámica etiquetas de carga previa. De esa manera, puedes minimizar el consumo de datos y ahorrar costos para los usuarios con planes de datos lentos o costosos.

Para implementar la carga previa adaptable, primero quita la etiqueta <link rel="prefetch"> de views/index.html:

<!doctype html>
  <html>
    <head>
       <meta charset="UTF-8">
       <meta name="viewport" content="width=device-width, initial-scale=1.0">
       <link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet">
       <link rel="prefetch" href="/product-details.html" as="document">
       ...
    </head>

Luego, agrega el siguiente código a public/script.js para declarar una función que inserte dinámicamente la etiqueta prefetch cuando el usuario tenga una conexión rápida:

function injectLinkPrefetchIn4g(url) {
    if (window.navigator.connection.effectiveType === '4g') {
        //generate link prefetch tag
        const linkTag = document.createElement('link');
        linkTag.rel = 'prefetch';
        linkTag.href = url;
        linkTag.as = 'document';

        //inject tag in the head of the document
        document.head.appendChild(linkTag);
    }
}

La función funciona de la siguiente manera:

  • Verifica la propiedad effectiveType de la API de Network Information para determinar si el usuario está en una conexión 4G (o más rápida).
  • Si se cumple esa condición, se genera una etiqueta <link> con prefetch como el tipo de sugerencia, se pasa la URL que se cargará previamente en el atributo href y se indica que el recurso es un document HTML en el atributo as.
  • Por último, inserta la secuencia de comandos de forma dinámica en el head de la página.

A continuación, agrega script.js a views/index.html, justo antes de la etiqueta de cierre </body>:

<body>
      ...
      <script src="/script.js"></script>
</body>

Solicitar script.js al final de la página garantiza que se cargará y ejecutará después de que se analice y cargue la página.

Para asegurarte de que la carga previa no interfiera en los recursos críticos de la página actual, agrega el siguiente fragmento de código para llamar a injectLinkPrefetchIn4g() en el evento window.load:

<body>
      ...
      <script src="/script.js"></script>
      <script>
           window.addEventListener('load', () => {
                injectLinkPrefetchIn4g('/product-details.html');
           });
      </script>
</body>

La página de destino ahora carga previamente product-details.html solo en conexiones rápidas Para verificar lo siguiente:

  1. Para obtener una vista previa del sitio, presiona Ver app. Luego, presiona Pantalla completa pantalla completa.
  2. Presiona "Control + Mayús + J" (o bien "Comando + Opción + J" en Mac) para abrir Herramientas para desarrolladores.
  3. Haga clic en la pestaña Red.
  4. En la lista desplegable Regulación, selecciona En línea.
  5. Vuelve a cargar la app.

Deberías ver product-details.html en el panel Network:

Panel Network que muestra product-details.html con carga previa.

Para verificar que la página del producto no tenga cargas previas en conexiones lentas, haz lo siguiente:

  1. En la lista desplegable Regulación, selecciona 3G lenta.
  2. Vuelve a cargar la app.

El panel Network solo debe incluir los recursos de la página de destino sin product-details.html:

Panel Network que muestra que no se realiza una carga previa de product-details.html.

El encabezado HTTP Link se puede usar para realizar una carga previa del mismo tipo de recursos que la etiqueta link. Decidir cuándo usar una de las dos opciones depende principalmente de tu preferencia, ya que la diferencia en el rendimiento es insignificante. En este caso, lo usarás para cargar previamente el CSS principal de la página del producto y mejorar aún más su renderización.

Agrega un encabezado HTTP Link para style-product.css en la respuesta del servidor de la página de destino:

  1. Abre el archivo server.js y busca el controlador get() para la URL raíz: /.
  2. Agrega la siguiente línea al comienzo del controlador:
app.get('/', function(request, response) {
    response.set('Link', '</style-product.css>; rel=prefetch');
    response.sendFile(__dirname + '/views/index.html');
});
  1. Para obtener una vista previa del sitio, presiona Ver app. Luego, presiona Pantalla completa pantalla completa.
  2. Presiona "Control + Mayús + J" (o bien "Comando + Opción + J" en Mac) para abrir Herramientas para desarrolladores.
  3. Haga clic en la pestaña Red.
  4. Vuelve a cargar la app.

El elemento style-product.css ahora se realiza una carga previa con la prioridad más baja después de que se carga la página de destino:

Panel Network que muestra las cargas previas style-product.css.

Para navegar a la página del producto, haz clic en Comprar ahora. Observa el panel Red:

Panel Network que muestra style-product.css recuperado de la caché de carga previa.

El archivo style-product.css se recupera de la "caché de carga previa" y solo tardó 12 ms en cargarse.