Precarga los recursos críticos para mejorar la velocidad de carga

Cuando abres una página web, el navegador solicita el documento HTML a un servidor, analiza su contenido y envía solicitudes independientes para los recursos a los que se hace referencia. Como desarrollador, ya conoces todos los recursos que necesita tu página y cuáles son los más importantes. Puedes usar esa información para solicitar los recursos críticos con anticipación y acelerar el proceso de carga. En esta publicación, se explica cómo lograrlo con <link rel="preload">.

Cómo funciona la carga previa

La precarga es más adecuada para los recursos que el navegador suele descubrir tarde.

Captura de pantalla del panel Network de Chrome DevTools.
En este ejemplo, la fuente Pacifico se define en la hoja de estilo con una regla @font-face. El navegador carga el archivo de fuente solo después de terminar de descargar y analizar la hoja de estilo.

Cuando se precarga un recurso determinado, se le indica al navegador que deseas recuperarlo antes de que lo descubra, ya que tienes la certeza de que es importante para la página actual.

Captura de pantalla del panel Network de Chrome DevTools después de aplicar la carga previa.
En este ejemplo, la fuente Pacifico está precargada, por lo que la descarga se realiza en paralelo con la hoja de estilo.

La cadena de solicitudes críticas representa el orden de los recursos que el navegador prioriza y recupera. Lighthouse identifica los recursos que se encuentran en el tercer nivel de esta cadena como descubiertos tardíamente. Puedes usar la auditoría Preload key requests para identificar qué recursos se deben precargar.

Auditoría de solicitudes de claves de carga previa de Lighthouse.

Para precargar recursos, agrega una etiqueta <link> con rel="preload" al encabezado de tu documento HTML:

<link rel="preload" as="script" href="critical.js">

El navegador almacena en caché los recursos precargados para que estén disponibles de inmediato cuando sea necesario. (no ejecuta las secuencias de comandos ni aplica los diseños de página).

Las sugerencias de recursos, por ejemplo, preconnect y prefetch, se ejecutan según lo considere conveniente el navegador. Por otro lado, preload es obligatorio para el navegador. Los navegadores modernos ya son bastante buenos para priorizar los recursos, por lo que es importante usar preload con moderación y solo precargar los recursos más críticos.

Las cargas previas que no se usan activan una advertencia de la consola en Chrome, aproximadamente 3 segundos después del evento load.

Advertencia de la consola de Herramientas para desarrolladores de Chrome sobre recursos precargados sin usar.

Casos de uso

Carga previa de recursos definidos en CSS

Las fuentes definidas con reglas @font-face o las imágenes de fondo definidas en archivos CSS no se descubren hasta que el navegador descarga y analiza esos archivos CSS. La carga previa de estos recursos garantiza que se recuperen antes de que se descarguen los archivos CSS.

Carga previa de archivos CSS

Si usas el enfoque de CSS crítico, divides el CSS en dos partes. El CSS crítico necesario para renderizar el contenido de la mitad superior de la página se intercala en el <head> del documento y el CSS no crítico suele cargarse de forma diferida con JavaScript. Esperar a que se ejecute JavaScript antes de cargar CSS no crítico puede causar demoras en la renderización cuando los usuarios se desplazan, por lo que es recomendable usar <link rel="preload"> para iniciar la descarga antes.

Carga previa de archivos JavaScript

Debido a que los navegadores no ejecutan archivos precargados, la carga previa es útil para separar la recuperación de la ejecución, lo que puede mejorar métricas como el tiempo de interacción. La carga previa funciona mejor si divides tus paquetes de JavaScript y solo cargas previamente los fragmentos críticos.

Cómo implementar rel=preload

La forma más sencilla de implementar preload es agregar una etiqueta <link> a la <head> del documento:

<head>
  <link rel="preload" as="script" href="critical.js">
</head>

Proporcionar el atributo as ayuda al navegador a establecer la prioridad del recurso recuperado previamente según su tipo, establecer los encabezados correctos y determinar si el recurso ya existe en la caché. Los valores aceptados para este atributo incluyen script, style, font, image y otros.

Algunos tipos de recursos, como las fuentes, se cargan en el modo anónimo. Para ellos, debes establecer el atributo crossorigin con preload:

<link rel="preload" href="ComicSans.woff2" as="font" type="font/woff2" crossorigin>

Los elementos <link> también aceptan un atributo type, que contiene el tipo MIME del recurso vinculado. Los navegadores usan el valor del atributo type para asegurarse de que los recursos se carguen previamente solo si su tipo de archivo es compatible. Si un navegador no admite el tipo de recurso especificado, ignorará el <link rel="preload">.

También puedes precargar cualquier tipo de recurso a través del encabezado HTTP Link:

Link: </css/style.css>; rel="preload"; as="style"

Un beneficio de especificar preload en el encabezado HTTP es que el navegador no necesita analizar el documento para descubrirlo, lo que puede ofrecer pequeñas mejoras en algunos casos.

Cómo precargar módulos de JavaScript con webpack

Si usas un empaquetador de módulos que crea archivos de compilación de tu aplicación, debes verificar si admite la inserción de etiquetas de carga previa. Con webpack versión 4.6.0 o posterior, la carga previa se admite mediante el uso de comentarios mágicos dentro de import():

import(_/* webpackPreload: true */_ "CriticalChunk")

Si usas una versión anterior de webpack, usa un complemento de terceros, como preload-webpack-plugin.

Efectos de la carga previa en las Métricas web esenciales

La precarga es una potente optimización del rendimiento que afecta la velocidad de carga. Estas optimizaciones pueden generar cambios en las métricas web esenciales de tu sitio, por lo que es importante que las tengas en cuenta.

Largest Contentful Paint (LCP)

La carga previa tiene un efecto potente en el procesamiento de imagen con contenido más grande (LCP) en el caso de las fuentes y las imágenes, ya que tanto las imágenes como los nodos de texto pueden ser candidatos para el LCP. Las imágenes hero y los grandes tramos de texto que se renderizan con fuentes web pueden beneficiarse significativamente de una sugerencia de carga previa bien ubicada y deben usarse cuando haya oportunidades para entregar estos fragmentos de contenido importantes al usuario más rápido.

Sin embargo, debes tener cuidado con la carga previa y otras optimizaciones. En particular, evita precargar demasiados recursos. Si se priorizan demasiados recursos, en realidad ninguno de ellos lo es. Los efectos de las sugerencias de carga previa excesiva serán especialmente perjudiciales para aquellos que tengan redes más lentas, donde la contención de ancho de banda será más evidente.

En su lugar, enfócate en algunos recursos de alto valor que sepas que se beneficiarán de una carga previa bien ubicada. Cuando precargues fuentes, asegúrate de publicar fuentes en formato WOFF 2.0 para reducir el tiempo de carga de recursos tanto como sea posible. Dado que WOFF 2.0 tiene una excelente compatibilidad con los navegadores, el uso de formatos más antiguos, como WOFF 1.0 o TrueType (TTF), retrasará tu LCP si el candidato a LCP es un nodo de texto.

En el caso de LCP y JavaScript, te recomendamos que te asegures de enviar un marcado completo desde el servidor para que el escáner de carga previa del navegador funcione correctamente. Si publicas una experiencia que depende por completo de JavaScript para renderizar el marcado y no puedes enviar HTML renderizado por el servidor, sería conveniente intervenir donde el escáner de carga previa del navegador no puede hacerlo y precargar recursos que, de otro modo, solo se podrían descubrir cuando JavaScript termine de cargarse y ejecutarse.

Cumulative Layout Shift (CLS)

El desplazamiento del diseño acumulativo (CLS) es una métrica especialmente importante en el caso de las fuentes web, y tiene una interacción significativa con las fuentes web que usan la propiedad CSS font-display para administrar la forma en que se cargan las fuentes. Para minimizar los cambios de diseño relacionados con las fuentes web, considera las siguientes estrategias:

  1. Precarga las fuentes mientras usas el valor predeterminado de block para font-display. Este es un equilibrio delicado. Bloquear la visualización de fuentes sin un resguardo se puede considerar un problema de experiencia del usuario. Por un lado, cargar fuentes con font-display: block; elimina los cambios de diseño relacionados con las fuentes web. Por otro lado, si son fundamentales para la experiencia del usuario, debes cargar esas fuentes web lo antes posible. Combinar una carga previa con font-display: block; puede ser una solución aceptable.
  2. Precarga las fuentes mientras usas el valor fallback para font-display. fallback es un compromiso entre swap y block, ya que tiene un período de bloqueo extremadamente corto.
  3. Usa el valor optional para font-display sin una carga previa. Si una fuente web no es fundamental para la experiencia del usuario, pero se usa para renderizar una cantidad significativa de texto de la página, considera usar el valor optional. En condiciones adversas, optional mostrará el texto de la página en una fuente de resguardo mientras carga la fuente en segundo plano para la próxima navegación. El resultado neto en estas condiciones es un CLS mejorado, ya que las fuentes del sistema se renderizarán de inmediato, mientras que las cargas de páginas posteriores cargarán la fuente de inmediato sin cambios de diseño.

El CLS es una métrica difícil de optimizar en el caso de las fuentes web. Como siempre, experimenta en el laboratorio, pero confía en tus datos de campo para determinar si tus estrategias de carga de fuentes mejoran el CLS o lo empeoran.

Interaction to Next Paint (INP)

Interaction to Next Paint es una métrica que mide la capacidad de respuesta a las entradas del usuario. Dado que la mayor parte de la interactividad en la Web se basa en JavaScript, la carga previa de JavaScript que potencia interacciones importantes puede ayudar a mantener un INP más bajo en una página. Sin embargo, ten en cuenta que la carga previa de demasiado JavaScript durante el inicio puede tener consecuencias negativas no deseadas si demasiados recursos compiten por el ancho de banda.

También debes tener cuidado con la forma en que realizas la división de código. El fraccionamiento de código es una excelente optimización para reducir la cantidad de JavaScript cargado durante el inicio, pero las interacciones pueden retrasarse si dependen de JavaScript cargado justo al comienzo de la interacción. Para compensar esto, deberás examinar la intención del usuario y, luego, insertar una carga previa para los fragmentos necesarios de JavaScript antes de que se produzca la interacción. Un ejemplo podría ser la carga previa de JavaScript necesaria para validar el contenido de un formulario cuando se enfoca cualquiera de sus campos.

Conclusión

Para mejorar la velocidad de la página, precarga los recursos importantes que el navegador descubre tarde. Precargar todo sería contraproducente, así que usa preload con moderación y mide el impacto en el mundo real.