Etiquetas HTML de precarga

Resource Hints: Precarga anticipada de enlaces


Las etiquetas HTML de precarga (resource hints) son una serie de etiquetas <link> que permiten dar al navegador algo de información adicional para saber a que recursos debe darles mayor prioridad, cargar de forma anticipada, posponer o incluso prerenderizar.

Por norma general, el navegador establece una prioridad concreta a cada recurso de una web, ya sea al propio fichero .html inicial, a los archivos .css o .js relacionados con el documento HTML, a las imágenes, tipografías, etc. Esta prioridad depende de una gran variedad de factores y casuísticas complejas, pero se dividen en las siguientes:

  • HIGHEST (Altísima prioridad)
  • HIGH
  • MEDIUM
  • LOW
  • LOWEST (bajísima prioridad)

Etiquetas de precarga

Estos valores se pueden modificar de muchas formas, pero uno de los métodos para modificarlos es utilizar las etiquetas <link> que comentaremos a continuación.

Atributo rel Descripción
dns-prefetch Indica un nombre de dominio que debería resolverse lo antes posible.
preconnect Indica una URL a la que debería preconectarse (DNS, handshake, TLS...) lo antes posible.
prefetch Indica una URL que se necesitará en el futuro y debería prepararse.
prerender Indica una URL que debería renderizarse porque es muy probable que el usuario acceda.
modulepreload Indica una URL con un módulo Javascript que debe precargar lo antes posible.
preload Indica una URL que debe precargarse inmediatamente para su utilización posterior.

Veamos como funciona cada uno de ellos en las siguientes secciones.

Antes de continuar, recuerda que el proceso de optimización de una página es delicado y complejo. No se trata de añadir una etiqueta de precarga por cada fichero, sino elegir cuales son los que producen cuellos de botella y anticiparlos. Añadir muchas etiquetas de precarga conseguiría justo el efecto contrario: relentizar la carga.

Por dominio

Precarga de resolución DNS

Antes de cargar un enlace con un recurso, ya sea una imagen, un fichero css, html o de cualquier otro tipo, el navegador debe resolver las DNS. Básicamente es un proceso que debe hacer al principio de cada recurso que esté alojado en un dominio desconocido, para conocer la IP que está detrás de ese dominio y por lo tanto poderse comunicar de forma más rápida y efectiva.

En muchas ocasiones, esta carga del dominio DNS se realiza muy tarde y se puede perder algún tiempo precioso en ello. Con esta etiqueta, podremos aprovechar «tiempos muertos» iniciales en realizar esa tarea, de modo que cuando descubra esos recursos ya pueda acceder a ellos sin perder el tiempo en resolver el DNS. Es decir, anticipamos esa tarea de resolver DNS.

El código a incluir sería el siguiente:

<head>
  <link rel="dns-prefetch" href="https://fonts.google.com/">
</head>

Como se puede ver, en este caso estamos indicando que resuelva las DNS de la página https://fonts.google.com, donde en muchas ocasiones se enlazan tipografías desde nuestro sitio. Ten muy en cuenta que en muchos casos, dentro de estas páginas, se cargan más recursos con nuevos dominios o CDN diferentes que también habría que incluir para que sea 100% efectiva esta tarea.

Preconexión a un dominio

Cada vez que el navegador tiene que realizar la carga de un recurso, por cada dominio debe realizar varias tareas:

  • Búsqueda y resolución de DNS
  • Negociación TCP (Handshake)
  • Negociación TLS (Opcional)

Estas tareas se pueden realizar de forma anticipada para ganar algún tiempo y aprovecharlo en otras tareas.

<head>
  <link rel="preconnect" href="https://cdnjs.com/">
</head>

Observa que mientras que la etiqueta anterior sólo realiza el proceso de resolución DNS, esta etiqueta incorpora más etapas, realizando una preconexión al dominio en cuestión.

Por URL

Prerender

En algunas situaciones, el usuario se encuentra navegando por una página donde, posteriormente, tiene un enlace para acceder a una página donde la probabilidad de acceder es bastante alta. Ejemplos de este caso suelen ser landing page o páginas similares, donde la intención directa es enviar al usuario a una sección específica.

Con la siguiente etiqueta podemos indicar al navegador que esa probabilidad es tan alta, que queremos que la página se vaya no sólo precargando sino prerenderizando de forma transparente en el navegador. Esto hará que cuando el usuario haga click en el enlace, la página esté instantáneamente precargada y predibujada en el navegador.

<head>
  <link rel="prerender" href="https://manz.dev/streams">
</head>

Ten en cuenta que esta etiqueta debe usarse sólo en casos muy específicos donde el usuario es muy probable que acceda, ya que el navegador va a precargar todo su contenido y dibujarlo en el navegador, por lo que si finalmente no entra, habrá desperdiciado tiempo y recursos.

Por recurso

Descarga anticipada

Mediante la etiqueta <link rel="prefetch"> podemos indicar al navegador que queremos que un recurso de la página se proponga para ser descargado desde que el navegador tenga tiempo libre en su proceso de carga inicial.

<head>
  <link rel="prefetch" href="https://manz.dev/additional.css" as="styles">
</head>

Observa que es necesario indicar en el atributo as la naturaleza del recurso especificado, ya que de lo contrario el navegador no tiene forma de saber de que tipo de recursos se trata (y muchas veces no se debe confiar en la extensión del fichero). En tipos de recursos puedes ver más información de los valores a utilizar.

Mucho cuidado con confundir prefetch con preload, que aunque tienen un objetivo parecido, hay ciertos matices que los diferencian.

Precarga de archivo

Si lo que necesitamos es realizar la precarga de un archivo por anticipado, la etiqueta <link rel="preload"> es la opción correcta. Esta etiqueta permite precargar recursos inmediatamente, con altísima prioridad. Suele ser una buena práctica para tipografías que utilizas en el primer impacto visual de la página o de imágenes que tienes de cabecera o que producen un parpadeo a la hora de cargarlas.

<head>
  <link rel="preload" href="https://manz.dev/fonts/montserrat.woff2" as="font">
</head>

Observa que esta etiqueta requiere el uso del atributo as, donde deberás indicar el tipo de recurso.

Precarga de módulo

Aunque la etiqueta anterior puede utilizarse para precargar archivos javascript .js, existe una especialización de esta etiqueta denominada <link rel="modulepreload">. Funciona exactamente igual a la etiqueta anterior, sin embargo tiene una pequeña diferencia: además de precargar el recurso, lo añade a la lista de módulos por cargar del navegador, y revisa las dependencias que tiene para precargarlas también, lo que lo hace muy adecuado para módulos Javascript.

<head>
  <link rel="modulepreload" href="https://manz.dev/modules/module.js">
</head>

En este caso, el atributo as tiene por defecto el valor script, por lo que se puede omitir. El soporte de esta modalidad de etiqueta aún no es completa, por lo que puede que no funcione correctamente en algunos navegadores.

Tipos de recursos

En algunas de las etiquetas anteriores habrás comprobado que existe un atributo as donde hay que indicar el tipo de fichero a referenciar. A continuación muestro una tabla con los valores posibles a indicar en este campo:

Atributo as Descripción Formatos
document Documento HTML o enlaces utilizados en elementos <iframe>. .html
script Documento Javascript. .js
audio Archivo de audio que se puede utilizar en un elemento <audio>. .mp3, .ogg, .opus, ...
video Archivo de video que se puede utilizar en un elemento <video>. .mp4, .webm, ...
image Imagen o documento gráfico que es posible utilizar en <img> o <picture>. .jpg, .png, .webp, ...
font Tipografía cargada mediante la regla @font-face de CSS. .woff2, .woff, .ttf
style Documento de estilos CSS. .css
track Archivo de subtítulos utilizado en elementos <track>. .vtt
fetch Enlace al que se hace una petición XHR o fetch. Necesita el atributo crossorigin.

Recuerda indicar el valor apropiado en el atributo as, ya que de lo contrario no se sabrá de forma anticipada que tipo de recurso es, y no podrá precargarse el recurso indicado correctamente.

¿Quién soy yo?

Soy Manz, vivo en Tenerife (España) y soy streamer partner en Twitch y profesor. Me apasiona el universo de la programación web, el diseño y desarrollo web y la tecnología en general. Aunque soy full-stack, mi pasión es el front-end, la terminal y crear cosas divertidas y locas.

Puedes encontrar más sobre mi en Manz.dev