preloadadelanta un recurso que el navegador descubriría tarde; no mejora lo que ya está en el HTML. Úsalo con fuentes, la imagen LCP puesta por CSS o JavaScript y poco más.- Las fuentes precargadas necesitan
crossoriginaunque sean de tu dominio. Sin él, elpreloadno se reutiliza y la fuente puede descargarse dos veces. preconnectsolo vale para orígenes externos que vas a usar enseguida; el navegador cierra la conexión si no se usa en 10 segundos. Para el resto,dns-prefetch.prefetch, Speculation Rules y 103 Early Hints sirven a casos distintos: la siguiente navegación y los servidores que tardan en responder.- Google ha dicho que Googlebot no necesita estas pistas. Su efecto en SEO pasa por la experiencia del usuario y el LCP, no por el rastreo.
- Se comprueba en la consola de DevTools (avisos de preload sin usar), en la pestaña Network (prioridad y orden) y en Lighthouse.
Lo habitual es encontrar webs con una docena de <link rel="preload"> copiados de un tutorial: tres fuentes que ya estaban en el CSS, el logo, un script de analítica y una imagen que ni siquiera se usa en esa plantilla. El resultado es tráfico de red que compite con lo que sí importa y un aviso en la consola que nadie lee.
Separo cada pista (preload, preconnect, dns-prefetch, prefetch, modulepreload, Speculation Rules y 103 Early Hints), cuándo sirve cada una, los errores más caros con una prueba propia y qué hay de todo esto en cristofercruz.net, medido con Playwright.

Qué son los resource hints y qué no hacen
Un resource hint es una indicación que le das al navegador sobre un recurso o un origen antes de que él mismo lo descubra. Se escribe como <link rel="..."> en el <head> o como cabecera HTTP Link. La guía de web.dev sobre el tema deja una regla que conviene tener presente: las directivas preload deben limitarse a los recursos críticos que se descubren tarde.
La distinción importante es entre lo que es una orden y lo que es una sugerencia. Según web.dev, preload es una descarga obligatoria, no una pista; preconnect, en cambio, puede ignorarse o aplicarse a medias, porque mantener una conexión abierta cuesta recursos. Y ninguna de estas pistas cambia el contenido de tu página: solo cambian el momento en que el navegador empieza a trabajar.
| Pista | Qué adelanta | Para qué navegación | Coste si te equivocas |
|---|---|---|---|
preload | Descarga de un recurso concreto | La actual | Ancho de banda y prioridad robados a otros recursos |
modulepreload | Descarga y compilación de un módulo ES | La actual | Igual que preload |
preconnect | DNS, TCP y TLS con otro origen | La actual | Conexiones abiertas que no se usan |
dns-prefetch | Solo la resolución DNS | La actual o enlaces probables | Mínimo |
prefetch | Descarga con prioridad baja | La siguiente | Datos gastados si el usuario no navega |
| Speculation Rules | Prefetch o prerender de una página | La siguiente | Datos, CPU y analítica contaminada |
| 103 Early Hints | Preload y preconnect antes del 200 | La actual | Trabajo inútil si el recurso cambia de URL |
Preload: adelantar lo que se descubre tarde
El navegador lee el HTML a medida que llega y lanza las descargas de lo que va encontrando. Una imagen dentro de una etiqueta img se descubre pronto. Una fuente declarada en un @font-face no se pide hasta que el navegador ha descargado el CSS, ha calculado qué elementos la usan y sabe que la necesita. Una imagen LCP puesta como background-image o insertada por JavaScript espera todavía más. Ese tiempo muerto es el que preload recorta.
La guía de optimización del LCP de web.dev lo plantea así: el recurso LCP tiene que poder descubrirse en el HTML inicial; si solo aparece en un CSS o en un JavaScript externo, hay que precargarlo con prioridad alta. Cuando ya está en el HTML, el preload aporta poco, porque el escáner del navegador lo habría encontrado igual.

Fuentes
Es el caso más claro. Una fuente web no se descarga hasta que el texto que la usa está en el árbol de render, y eso retrasa el pintado del texto o provoca un cambio de fuente visible. Precargar las dos o tres variantes que se ven en la primera pantalla evita el salto.
<link rel="preload" href="/assets/fonts/nunito-400.woff2"
as="font" type="font/woff2" crossorigin>
El crossorigin no es opcional. MDN lo dice así: el precargado de font y fetch exige el atributo, y debe coincidir con el modo CORS y de credenciales del recurso aunque la petición no sea de otro origen. Las fuentes se piden en modo CORS anónimo; un preload sin crossorigin usa otro modo y el navegador no lo reutiliza cuando el CSS pide la fuente. En la sección de errores muestro la prueba.
Imagen LCP
Si la imagen principal va en una etiqueta img del HTML, lo que la acelera es no ponerle loading="lazy" y darle fetchpriority="high"; eso tiene su propio artículo sobre fetchpriority en SEO y no lo repito aquí. El preload entra cuando la imagen no se puede descubrir en el HTML (fondo CSS, carga por JavaScript) o cuando quieres que se pida antes que el CSS. Si es responsive, usa imagesrcset e imagesizes para que el navegador aplique la misma selección que con srcset; la parte de formatos y srcset está en la guía de optimización de imágenes.
<link rel="preload" as="image" type="image/webp"
href="/img/hero-800.webp"
imagesrcset="/img/hero-480.webp 480w, /img/hero-800.webp 800w"
imagesizes="(max-width: 1180px) 100vw, 40vw"
fetchpriority="high">
Una advertencia que recoge web.dev: preload no cambia la prioridad por sí solo. "Preload lets the browser discover a resource early, but it still fetches the resource with the default priority", así que una imagen precargada sin fetchpriority sigue pidiéndose con prioridad baja. Por eso los dos atributos se complementan.
Hojas de estilo y scripts
Para CSS y JavaScript críticos que se descubren tarde (un @import, un script cargado por otro script), as="style" y as="script" con su href. Aquí el fallo típico es omitir as: web.dev avisa de que equivale a una petición XHR y puede hacer que algunos recursos, como los scripts, se descarguen dos veces. Si lo que quieres es pintar antes, la solución suele estar más arriba: ver qué CSS bloquea el render y cuánto pesa, como cuento en la guía de CSS para SEO.
Los atributos que importan

as y el crossorigin son los que más se olvidan.| Atributo | Para qué sirve | Qué pasa si falta o está mal |
|---|---|---|
as | Fija la prioridad según el tipo, envía las cabeceras correctas y permite saber si ya está en caché. Valores en MDN: fetch, font, image, script, style, track | Se trata como XHR; posible doble descarga |
type | Tipo MIME; el navegador lo usa para decidir si precarga | Si no lo soporta, ignora el preload |
crossorigin | Modo CORS y credenciales de la petición | Fuentes: el preload no se reutiliza |
imagesrcset e imagesizes | Preload de imagen responsive | Descarga la versión equivocada |
fetchpriority | Sube o baja la prioridad de la descarga | Prioridad por defecto del tipo de recurso |
Regla para decidir en dos preguntas: ¿el navegador tardaría en descubrir este recurso? ¿Lo voy a usar en los primeros segundos? Si las dos respuestas no son sí, no lo precargues.
Preconnect y dns-prefetch: conexiones con otros orígenes
Abrir una conexión con un origen nuevo exige resolver el DNS, abrir TCP y negociar TLS antes de pedir el primer byte. preconnect hace ese trabajo por adelantado; dns-prefetch hace solo el primer paso. web.dev cifra la búsqueda DNS entre 20 y 120 ms, lo que da una idea de lo que se ahorra con el segundo y de por qué el primero ahorra más.

<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="dns-prefetch" href="https://fonts.gstatic.com">
Tres reglas que salen de la documentación de web.dev:
- Solo tiene sentido con orígenes distintos al tuyo. Con el propio dominio la conexión ya está abierta.
- Si el recurso se carga en modo anónimo (las fuentes), el
preconnectnecesitacrossorigin; sin él, el navegador solo hace la búsqueda DNS. - El navegador cierra la conexión si no se usa en 10 segundos, y demasiados
preconnectcompiten por ancho de banda. Reserva elpreconnectpara los orígenes más críticos y usadns-prefetchpara el resto.
Para el respaldo de navegadores antiguos, web.dev recomienda dos etiquetas separadas, una por cada valor, en lugar de rel="dns-prefetch preconnect" en una sola: en Safari esa combinación hace que el preconnect se cancele. Si tu CDN sirve los estáticos desde otro dominio, es el candidato natural a preconnect; cómo elegir y configurar el CDN está en el artículo sobre CDN y SEO.
Prefetch, prerender y Speculation Rules: la página siguiente
prefetch descarga un recurso con prioridad baja para una navegación futura y lo guarda en la caché HTTP. MDN lo marca como disponibilidad limitada y avisa de que, por la partición de caché, no sirve para recursos de otros sitios. También lo bloquean directivas Cache-Control como no-store, algo que enlaza con lo que cuento en la guía de caché para SEO.
Para documentos completos, MDN recomienda la Speculation Rules API donde esté soportada. Las reglas van en un bloque JSON y permiten dos acciones: prefetch (solo el documento) y prerender (la página entera, renderizada en segundo plano, lista para activarse al instante).
<script type="speculationrules">
{
"prerender": [{
"where": { "href_matches": "/blog/*" },
"eagerness": "moderate"
}]
}
</script>

eagerness decide cuándo se dispara.Lo que dice la documentación de Chrome Developers sobre el estado actual, que conviene releer antes de implementarlo porque cambia con las versiones:
- El prerender funciona en Chrome y Edge desde la versión 109; Firefox no lo soporta y Safari lo tiene tras un flag. Es una mejora progresiva: en los navegadores que no lo entienden, no pasa nada.
- El
eagernessadmiteconservative(al pulsar),moderate(en escritorio, tras 200 ms de hover),eagereimmediate. Por defecto, las reglas de lista usanimmediatey las de documento,conservative. - La analítica puede contar páginas prerenderizadas que el usuario nunca ve; con herramientas que no lo gestionen, usa
document.prerenderingy el eventoprerenderingchange.
Lo que no he encontrado documentado es cómo trata Googlebot estas reglas. No lo afirmo en un sentido ni en otro. Para el SEO, la ventaja es indirecta: una navegación que se siente instantánea mejora la experiencia, y el riesgo es de medición, no de indexación.
modulepreload: módulos ES
Con módulos ES, preload as="script" solo descarga el archivo. Según MDN, modulepreload descarga, analiza y compila el módulo y lo deja en el module map del documento. El navegador puede buscar las dependencias por su cuenta, pero no está obligado: para asegurarlo, declara cada una con su propio link.
<link rel="modulepreload" href="/js/main.js">
<link rel="modulepreload" href="/js/utils.js">
<script type="module" src="/js/main.js"></script>
Es para aplicaciones con dependencias en cascada; en una web de contenidos con un par de scripts defer no aporta nada. Que el contenido llegue al HTML se decide antes, en la guía de JavaScript SEO.
103 Early Hints: pistas antes de la respuesta
Mientras el servidor genera el HTML (consultas a base de datos, renderizado en servidor), el navegador está parado. 103 Early Hints es una respuesta HTTP preliminar que el servidor puede enviar antes del 200 con cabeceras Link, para que el navegador empiece a descargar lo crítico durante ese tiempo.

HTTP/2 103
link: </assets/app.css>; rel=preload; as=style
link: <https://cdn.example.com>; rel=preconnect
HTTP/2 200
content-type: text/html
Según la documentación de Chrome Developers:
- Se recomienda enviarlo solo sobre HTTP/2 o HTTP/3, y solo a peticiones de navegación (
sec-fetch-mode: navigate), porque algunos clientes antiguos o bots pueden tener problemas con las respuestas informativas. - Soporte de
preconnecten Early Hints: Chrome 103, Edge 103, Firefox 120 y Safari 17. Depreload: Chrome 103, Edge 103 y Firefox 123; Safari no. - Chrome no admite
prefetchen Early Hints. - Los recursos tienen que ser cacheables o se descargan dos veces.
- Si el servidor puede contestar con el 200 al instante, la propia documentación recomienda usar
preloadopreconnectnormales.
La página cita a Cloudflare, Fastly y Akamai como plataformas con soporte. No he probado Early Hints para este artículo y prefiero decirlo que enseñar un resultado que no he visto.
Qué hace Googlebot con las resource hints
El 26 de febrero de 2026, Search Engine Journal recogió lo que Gary Illyes y Martin Splitt dijeron en el podcast Search Off the Record: estas pistas resuelven problemas de latencia del navegador del usuario que la infraestructura de Google no tiene. Del DNS, Illyes comentó que el dns-prefetch es muy útil si tienes una conexión mala, pero que Google llega muy rápido a los servidores DNS. La lista de las cuatro pistas ignoradas (dns-prefetch, preload, prefetch, preconnect) es el resumen del medio, no una cita literal.
La consecuencia práctica: no son una palanca de rastreo ni de indexación. Su efecto en SEO pasa por la experiencia del usuario: mejor LCP en datos de campo, menos salto de fuente, navegaciones más rápidas.
Relación con el LCP
Web.dev descompone el LCP en cuatro partes: TTFB, retraso de carga del recurso, duración de la carga y retraso de renderizado, con unas proporciones orientativas de 40 %, menos de 10 %, 40 % y menos de 10 %. Las pistas atacan sobre todo la segunda: el tiempo entre que llega el HTML y empieza a descargarse el recurso LCP. Si tu LCP lo domina el TTFB o el peso de la imagen, precargar no mueve nada. Los umbrales y las causas están en la guía de Core Web Vitals; la comprobación es empírica: mides el desglose, añades la pista y vuelves a medir.
Errores frecuentes, con una prueba propia

Monté una página de prueba con Chromium 141 (Playwright) y un servidor mínimo que registra cada petición. Tenía una fuente con preload correcto, otra con preload sin crossorigin, una tercera fuente precargada sin ser usada y una imagen precargada con as="image" que tampoco se usaba. Esto es lo que vi en la consola:
A preload for 'http://127.0.0.1:8731/g.woff2' is found, but is not used because
the request credentials mode does not match. Consider taking a look at
crossorigin attribute.
The resource http://127.0.0.1:8731/img.webp was preloaded using link preload
but not used within a few seconds from the window's load event. Please make
sure it has an appropriate `as` value and it is preloaded intentionally.
El primer aviso es el de la fuente sin crossorigin; el segundo, el de cualquier recurso precargado que no se usa (lo mostró también para las dos fuentes sobrantes). Después hice la prueba de la doble descarga, con dos configuraciones del servidor:
| Cabecera de caché del servidor | Peticiones al servidor de la fuente sin crossorigin | Peticiones de la fuente correcta |
|---|---|---|
Cache-Control: no-store | 2 | 1 |
Cache-Control: max-age=3600 | 1 (la segunda salió de la caché HTTP) | 1 |
Es decir, con una respuesta cacheable, la doble descarga de una fuente sin crossorigin no llegó al servidor en mi prueba, aunque el preload seguía siendo inútil y el aviso aparecía igual. Con no-store sí hubo dos peticiones. Es una prueba de laboratorio con un solo navegador y archivos locales, no una regla general: el resultado depende de las cabeceras de caché del recurso, y la documentación de Chrome sobre Early Hints dice lo mismo para los recursos no cacheables.
Otros fallos que veo en auditorías:
- Preload de lo que no se usa en esa plantilla. Un tema que precarga la fuente del carrusel en todas las páginas, haya carrusel o no. DebugBear lo resume bien: suele ser un
preload(prioridad alta) donde se quería unprefetch(prioridad baja), o un recurso retirado de la página cuya etiqueta se quedó. fetchpriority="high"en todo lo precargado. web.dev avisa de que poner prioridad alta en más de una o dos imágenes deja de servir para algo.- Precargar la imagen que además lleva
loading="lazy". Se contradicen; el criterio sobre qué cargar de forma diferida está en la guía de carga diferida.
Cómo lo tengo en mi web
Esto es lo que hay en cristofercruz.net, leído en includes/header.php y medido en local con Playwright (Chromium 141) en la home y en un artículo del blog. Los tiempos en localhost no significan nada, así que solo cuento qué se pide, en qué orden y con qué prioridad.

| Pista | Estado en mi web |
|---|---|
preload de fuentes | Sí: DM Serif Display 400, Nunito 400 y Nunito 700, con as="font", type="font/woff2" y crossorigin, en todas las páginas con el diseño actual |
preload de imagen | Solo en la home: el retrato principal, con imagesrcset (480 y 800 px), imagesizes y fetchpriority="high" |
preconnect y dns-prefetch | No. No hay ninguna petición a otro origen en mis páginas |
prefetch y Speculation Rules | No |
modulepreload | No: los scripts son clásicos con defer |
Cabeceras Link y 103 Early Hints | No desde mi código ni mi .htaccess. Si el CDN que haya delante los añade, no lo he verificado |
Lo que medí:
- Blog, escritorio (1366 px). Orden de peticiones: el documento, las tres fuentes precargadas (prioridad High), el script del consentimiento de cookies, el logo, el avatar, la portada del artículo (prioridad High, por su
fetchpriority="high") y los otros dos scripts. Tras ellos llegan Nunito 600 y la cursiva de DM Serif, que no están precargadas, con prioridad VeryHigh porque las pide el layout. El elemento LCP fue la portada. - Blog, móvil (390 px). La portada no se descarga (en pantallas de menos de 900 px el
picturesirve un GIF de un píxel) y el elemento LCP fue elh1, texto. Ahí las fuentes precargadas sí pesan en el LCP. - Home. Las tres fuentes y el retrato son las primeras peticiones tras el documento, ambas con prioridad High.
- Origen de las peticiones. En todas las pruebas, cero peticiones a otros orígenes. Hoy no hay ningún proveedor de analítica activo en la configuración del sitio, así que no hay un tercero que justifique un
preconnect.
Hay dos huecos que he visto al medir. La portada del artículo no se precarga: no hace falta, porque va en el HTML y lleva fetchpriority="high", pero el navegador no la pide hasta después de dos scripts y un par de imágenes. Y dos variantes de fuente (Nunito 600 y la cursiva de DM Serif) se descubren tarde. Si alguna de las dos se ve en la primera pantalla, es candidata a preload; no he medido si cambia el LCP o el CLS, así que de momento no lo toco.
Cómo auditarlo
El orden que sigo en una auditoría, de menos a más esfuerzo:
- Consola de DevTools. Recarga la página y busca los avisos de
preload: el de not used within a few seconds y el de credentials mode does not match. Cada uno es un error a corregir. - Pestaña Network, columna Priority. Actívala con clic derecho en la cabecera de la tabla. Comprueba que la imagen LCP y las fuentes críticas salen pronto y con prioridad alta, y que no hay dos filas para el mismo archivo.
- Cascada y subpartes del LCP. En Performance o en PageSpeed Insights, mira el retraso de carga del recurso LCP. Si es alto y el recurso no está en el HTML, es el candidato a
preload. - Código fuente. Lista los
<link rel="preload|preconnect|dns-prefetch|prefetch">conview-sourcey comprueba que cada uno tiene un uso real en esa plantilla. - Cabeceras.
curl -Iy buscalink:por si hay pistas enviadas desde el servidor o el CDN.
Cambia una cosa cada vez y mide antes y después con el mismo perfil de red; con tres preloads a la vez no sabrás cuál ayuda.
Preguntas frecuentes
¿Preload mejora el posicionamiento?
No de forma directa. Google ha dicho que Googlebot ignora estas pistas. Lo que puede mejorar es el LCP y la experiencia de los usuarios, y eso sí está dentro de las señales de experiencia de página.
¿Cuántos preloads puedo poner?
No hay un número mágico documentado. La guía de web.dev pide limitarlos a los recursos críticos que se descubren tarde, y como preload tiene prioridad alta, abusar de él puede saturar el ancho de banda. En la práctica, dos o tres fuentes y una imagen es lo máximo que suelo ver justificado.
¿Por qué mis fuentes se descargan dos veces?
Lo más probable es que el preload no lleve crossorigin. Las fuentes se piden en modo CORS anónimo, y un preload sin ese atributo usa otro modo, así que no se reutiliza. Si además el recurso no es cacheable, el navegador lo pide dos veces; en mi prueba, con max-age la segunda salió de la caché.
¿Preconnect o dns-prefetch?
preconnect para los pocos orígenes críticos que vas a usar en los primeros segundos; dns-prefetch para el resto y como alternativa más barata. Recuerda poner crossorigin en el preconnect de recursos anónimos como las fuentes.
¿Hace falta preload si ya uso fetchpriority="high"?
Depende de dónde esté la imagen. Si va en una etiqueta img del HTML, fetchpriority="high" suele bastar. Si la pone el CSS o JavaScript, necesitas el preload para que se descubra pronto, y es buena idea añadirle también fetchpriority="high".
Referencias
- Preload critical assets to improve loading speed web.dev · Google
- Establish network connections early to improve perceived page speed web.dev · Google
- Optimize Largest Contentful Paint web.dev · Google
- Early Hints Chrome for Developers
- Prerender pages in Chrome for instant page navigations Chrome for Developers
- Google explains why its crawler ignores your resource hints Search Engine Journal
- Common rel=preload problems DebugBear




