Ver contenido
Introducción
Esta guía completa te lleva a través de estrategias avanzadas de implementación de fetchpriority. Aprenderás a depurar problemas de prioridad, combinar fetchpriority con otras técnicas de optimización y construir un enfoque sistemático para la priorización de recursos.
Lo que aprenderás:
- Identificar elementos LCP para optimización de prioridad
- Depurar prioridad de recursos en Chrome DevTools
- Combinar fetchpriority con preload y preconnect
- Implementaciones específicas por framework
- Asignación dinámica de prioridad del lado del servidor
- Medir y validar mejoras
Tabla de Contenidos
- Identificando Tu Elemento LCP
- Depurando Prioridad en DevTools
- Combinando con Preload
- Implementaciones en Frameworks
- Asignación Dinámica de Prioridad
- Consideraciones del Lado del Servidor
- Estrategias de Prueba
- Midiendo el Impacto
- Patrones Comunes y Anti-Patrones
- Guía de Solución de Problemas
1. Identificando Tu Elemento LCP
Antes de agregar fetchpriority, debes identificar exactamente cuál elemento es tu LCP. Diferentes páginas pueden tener diferentes elementos LCP.
Usando PageSpeed Insights
- Navega a PageSpeed Insights
- Ingresa tu URL y ejecuta el análisis
- Desplázate a la sección “Diagnósticos”
- Encuentra “Elemento Largest Contentful Paint”
- Anota el selector del elemento y su tipo
Usando Lighthouse en DevTools
// En la Consola de DevTools, despues de ejecutar Lighthouse
const lcpEntry = performance.getEntriesByType('largest-contentful-paint')[0];
console.log('Elemento LCP:', lcpEntry.element);
console.log('Tiempo LCP:', lcpEntry.startTime);
Usando Performance Observer
Agrega esto a tu página para monitoreo de LCP en tiempo real:
new PerformanceObserver((entryList) => {
const entries = entryList.getEntries();
const lastEntry = entries[entries.length - 1];
console.log('Elemento LCP:', lastEntry.element);
console.log('Tiempo LCP:', lastEntry.startTime, 'ms');
console.log('URL LCP:', lastEntry.url || 'elemento de texto');
}).observe({ type: 'largest-contentful-paint', buffered: true });
Elementos LCP Comunes por Tipo de Página
| Tipo de Página | Elemento LCP Típico | Acción de Prioridad |
|---|---|---|
| Inicio | Imagen hero/banner | fetchpriority="high" en img hero |
| Producto | Imagen principal del producto | fetchpriority="high" en img producto |
| Blog | Imagen destacada o primer encabezado | fetchpriority="high" si es imagen |
| Categoría | Primera imagen de producto visible | fetchpriority="high" en primeras 1-2 |
| Landing page | Sección hero above-fold | fetchpriority="high" en imagen área CTA |
2. Depurando Prioridad en DevTools
Chrome DevTools proporciona herramientas para inspeccionar cómo los navegadores priorizan recursos.
Columna de Prioridad en Panel de Red
- Abre DevTools → pestaña Network (Red)
- Clic derecho en encabezados de columna → Habilitar “Priority” (Prioridad)
- Recarga la página
- Observa los valores de la columna de prioridad
Niveles de Prioridad Explicados:
| Prioridad | Descripción |
|---|---|
| Highest (Más alta) | Recursos que bloquean renderizado (CSS principal, scripts síncronos) |
| High (Alta) | Recursos críticos en el viewport |
| Medium (Media) | Scripts, imágenes visibles |
| Low (Baja) | Recursos below-fold, scripts async |
| Lowest (Más baja) | Prefetch, cargas especulativas |
Identificando Cambios de Prioridad
Los recursos pueden cambiar de prioridad durante la carga. Para ver cambios:
- Panel Network → Clic derecho → “Filas de solicitud grandes”
- Pasa el cursor sobre recursos para ver prioridad inicial vs final
- Busca recursos que comenzaron “Low” pero cambiaron a “High”
Cascada del Panel de Rendimiento
Para análisis más profundo:
- Pestaña Performance → Grabar carga de página
- Expande sección “Network”
- Observa tiempos de solicitud y orden
- Identifica cuellos de botella donde recursos de alta prioridad esperan
Depuración por Consola
// Registrar todas las imagenes y su fetch priority
document.querySelectorAll('img').forEach(img => {
console.log({
src: img.src.substring(img.src.lastIndexOf('/') + 1),
fetchPriority: img.fetchPriority || 'auto',
loading: img.loading || 'eager',
enViewport: img.getBoundingClientRect().top < window.innerHeight
});
});
3. Combinando con Preload
Entendiendo cuándo usar preload, fetchpriority, o ambos.
Preload vs Fetchpriority
| Técnica | Propósito | Caso de Uso |
|---|---|---|
<link rel="preload"> | Descubrir recurso antes | Recurso no en HTML inicial |
fetchpriority="high" | Aumentar prioridad una vez descubierto | Recurso en HTML pero necesita aumento de prioridad |
| Ambos juntos | Descubrimiento temprano + alta prioridad | Recurso crítico como imagen LCP |
Preload Sin Fetchpriority
Cuando la imagen está en contenido dinámico (cargado vía JavaScript):
<!-- Preload hace que el navegador conozca el recurso temprano -->
<link rel="preload" as="image" href="hero.webp">
<!-- Imagen cargada despues via JavaScript -->
<script>
// Imagen insertada dinamicamente
const img = document.createElement('img');
img.src = 'hero.webp';
document.querySelector('.hero').appendChild(img);
</script>
Fetchpriority Sin Preload
Cuando la imagen ya está en HTML pero necesita prioridad:
<!-- Imagen en HTML, solo necesita mayor prioridad -->
<img src="hero.webp"
alt="Imagen hero"
fetchpriority="high"
width="1200"
height="600">
Enfoque Combinado para Máximo Rendimiento
Para imágenes LCP que se benefician de ambos:
<head>
<!-- Descubrimiento temprano + alta prioridad -->
<link rel="preload"
as="image"
href="hero.webp"
fetchpriority="high">
</head>
<body>
<!-- Imagen aun recibe fetchpriority por consistencia -->
<img src="hero.webp"
alt="Imagen hero"
fetchpriority="high"
width="1200"
height="600">
</body>
Preconnect para Imágenes Externas
Si tu imagen LCP está en un CDN:
<head>
<!-- Establecer conexion temprano -->
<link rel="preconnect" href="https://cdn.ejemplo.com">
<!-- Luego preload con alta prioridad -->
<link rel="preload"
as="image"
href="https://cdn.ejemplo.com/hero.webp"
fetchpriority="high">
</head>
4. Implementaciones en Frameworks
React
// Componente React con fetchpriority
function HeroImage({ src, alt }) {
return (
<img
src={src}
alt={alt}
fetchpriority="high"
width={1200}
height={600}
/>
);
}
// Con componente Image de Next.js (v13+)
import Image from 'next/image';
function Hero() {
return (
<Image
src="/hero.webp"
alt="Hero"
priority // Esto establece fetchpriority="high"
width={1200}
height={600}
/>
);
}
Vue 3
<script setup>
// En Vue 3 con Vite
defineProps({
src: String,
alt: String,
priority: {
type: Boolean,
default: false
}
});
</script>
<template>
<img
:src="src"
:alt="alt"
:fetchpriority="priority ? 'high' : 'auto'"
width="1200"
height="600"
>
</template>
Nuxt 3
<template>
<NuxtImg
src="/hero.webp"
alt="Imagen hero"
:preload="true"
fetchpriority="high"
width="1200"
height="600"
/>
</template>
Angular
// Componente
@Component({
selector: 'app-hero-image',
template: `
<img [src]="src"
[alt]="alt"
[attr.fetchpriority]="priority ? 'high' : null"
[width]="1200"
[height]="600">
`
})
export class HeroImageComponent {
@Input() src: string;
@Input() alt: string;
@Input() priority = false;
}
Astro
---
// En componente .astro
const { src, alt, priority = false } = Astro.props;
---
<img
src={src}
alt={alt}
fetchpriority={priority ? 'high' : 'auto'}
width="1200"
height="600"
/>
5. Asignación Dinámica de Prioridad
A veces los elementos LCP varían por dispositivo o contenido.
Imágenes LCP Responsivas
Diferentes imágenes pueden ser LCP en diferentes viewports:
<picture>
<!-- LCP movil: hero mas pequeno -->
<source
media="(max-width: 768px)"
srcset="hero-mobile.webp"
fetchpriority="high">
<!-- LCP escritorio: hero completo -->
<source
srcset="hero-desktop.webp"
fetchpriority="high">
<img
src="hero-desktop.webp"
alt="Hero"
fetchpriority="high"
width="1200"
height="600">
</picture>
Prioridad Basada en JavaScript
Para contenido dinámico donde LCP varía:
// Establecer prioridad basada en posicion del viewport
document.addEventListener('DOMContentLoaded', () => {
const imagenes = document.querySelectorAll('img[data-auto-priority]');
imagenes.forEach(img => {
const rect = img.getBoundingClientRect();
const enViewport = rect.top < window.innerHeight && rect.bottom > 0;
if (enViewport && rect.height > 200) {
img.fetchPriority = 'high';
}
});
});
Asignación de Prioridad del Lado del Servidor
En Node.js/Express:
app.get('/producto/:id', async (req, res) => {
const producto = await getProducto(req.params.id);
// Determinar si producto tiene imagen hero grande
const heroNecesitaPrioridad = producto.imagenHero.height > 400;
res.render('producto', {
producto,
heroFetchPriority: heroNecesitaPrioridad ? 'high' : 'auto'
});
});
6. Consideraciones del Lado del Servidor
HTTP Early Hints (103)
Para descubrimiento de recursos aún más temprano:
HTTP/1.1 103 Early Hints
Link: </hero.webp>; rel=preload; as=image; fetchpriority=high
HTTP/1.1 200 OK
Content-Type: text/html
...
Implementación en Node.js
app.get('/', (req, res) => {
// Enviar early hints para recursos criticos
res.writeEarly({
link: '</hero.webp>; rel=preload; as=image; fetchpriority=high'
});
// Continuar con respuesta
res.render('home');
});
Prioridad Basada en CDN
Algunos CDNs soportan indicaciones automáticas de prioridad:
<!-- Ejemplo Cloudflare -->
<img src="hero.webp"
data-cf-priority="high"
alt="Hero">
7. Estrategias de Prueba
Prueba A/B del Impacto de Prioridad
// Prueba A/B simple para impacto de fetchpriority
const variante = Math.random() > 0.5 ? 'high' : 'auto';
// Rastrear que variante ve el usuario
analytics.track('fetchpriority_test', { variante });
// Aplicar variante
document.querySelector('.hero-img').fetchPriority = variante;
Pruebas Sintéticas
Usa WebPageTest para pruebas controladas:
- Ejecuta prueba sin fetchpriority
- Ejecuta prueba con fetchpriority=“high” en LCP
- Compara tiempos LCP a través de múltiples ejecuciones
- Usa filmstrip para visualizar diferencia
Monitoreo de Usuarios Reales (RUM)
// Rastrear LCP con contexto de fetchpriority
new PerformanceObserver((list) => {
const lcpEntry = list.getEntries().at(-1);
const lcpElement = lcpEntry.element;
const tieneFetchPriority = lcpElement?.fetchPriority === 'high';
analytics.track('lcp', {
tiempo: lcpEntry.startTime,
tieneFetchPriority,
tipoElemento: lcpElement?.tagName
});
}).observe({ type: 'largest-contentful-paint', buffered: true });
8. Midiendo el Impacto
Métricas Clave a Rastrear
| Métrica | Qué Muestra | Mejora Objetivo |
|---|---|---|
| LCP | Tiempo al elemento más grande | 10-30% más rápido |
| TTFB a LCP | Servidor a completitud visual | Brecha reducida |
| Tiempo de carga de imagen | Timing de recurso individual | Completitud más temprana |
| Cambios de prioridad | Frecuencia de re-priorización | Menos cambios |
Script de Comparación Antes/Después
// Ejecuta esto en DevTools antes y despues de agregar fetchpriority
const medirLCP = () => {
return new Promise(resolve => {
new PerformanceObserver((list) => {
const entries = list.getEntries();
resolve(entries[entries.length - 1].startTime);
}).observe({ type: 'largest-contentful-paint', buffered: true });
});
};
// Recolectar multiples muestras
const muestras = [];
for (let i = 0; i < 5; i++) {
location.reload();
muestras.push(await medirLCP());
}
console.log('LCP Promedio:', muestras.reduce((a, b) => a + b) / muestras.length);
Monitoreo en Google Search Console
Después de implementar fetchpriority:
- Ve a Search Console → Experiencia → Core Web Vitals
- Monitorea mejoras de LCP durante período de 28 días
- Rastrea aumento de porcentaje de “URLs buenas”
- Compara mejoras móvil vs escritorio
9. Patrones Comunes y Anti-Patrones
Patrones (Haz Esto)
Patrón 1: Prioridad Única para LCP
<!-- Solo la imagen LCP obtiene alta prioridad -->
<img src="hero.webp" fetchpriority="high" alt="Hero principal">
<img src="feature1.webp" alt="Caracteristica 1">
<img src="feature2.webp" alt="Caracteristica 2">
Patrón 2: Baja Explícita para Below-Fold
<img src="hero.webp" fetchpriority="high" alt="Hero">
<!-- Explicitamente baja para imagenes no criticas -->
<img src="footer-logo.webp" fetchpriority="low" loading="lazy" alt="Logo">
Patrón 3: Preload + Prioridad para LCP Externo
<head>
<link rel="preconnect" href="https://cdn.ejemplo.com">
<link rel="preload" as="image" href="https://cdn.ejemplo.com/hero.webp" fetchpriority="high">
</head>
Anti-Patrones (Evita Esto)
Anti-Patrón 1: Todo con Alta Prioridad
<!-- NO: Multiples alta prioridad diluye el efecto -->
<img src="hero.webp" fetchpriority="high">
<img src="producto1.webp" fetchpriority="high">
<img src="producto2.webp" fetchpriority="high">
<img src="producto3.webp" fetchpriority="high">
Anti-Patrón 2: Alta + Lazy
<!-- NO: Instrucciones contradictorias -->
<img src="hero.webp" fetchpriority="high" loading="lazy">
Anti-Patrón 3: Prioridad en Imágenes Pequeñas
<!-- NO: Desperdiciar prioridad en recursos pequenos -->
<img src="icono.svg" fetchpriority="high" width="24" height="24">
10. Guía de Solución de Problemas
LCP No Mejora
Posibles causas:
- Elemento incorrecto identificado como LCP
- Imagen ya cargando con alta prioridad
- Cuello de botella de red o servidor es el problema real
Solución:
// Verificar elemento LCP
new PerformanceObserver((list) => {
console.log('Elemento LCP:', list.getEntries().at(-1).element);
}).observe({ type: 'largest-contentful-paint', buffered: true });
Prioridad No Se Aplica
Verifica en DevTools:
- Pestaña Network → Columna Priority
- Verifica que atributo esté en código fuente HTML
- Verifica si JavaScript está sobrescribiendo atributo
Código de depuración:
const img = document.querySelector('.hero-img');
console.log('fetchPriority:', img.fetchPriority);
console.log('atributo:', img.getAttribute('fetchpriority'));
Navegador No Soporta Fetchpriority
Código de detección:
const soportaFeature = 'fetchPriority' in HTMLImageElement.prototype;
console.log('fetchPriority soportado:', soportaFeature);
Estrategia de respaldo: Usa preload para navegadores sin soporte de fetchpriority:
<link rel="preload" as="image" href="hero.webp">
Lista de Verificación de Implementación
- [ ] Identificar elemento LCP usando PageSpeed Insights o DevTools
- [ ] Agregar
fetchpriority="high"a imagen LCP - [ ] Remover cualquier
loading="lazy"de imagen LCP - [ ] Agregar
fetchpriority="low"a imágenes below-fold - [ ] Considerar preload para imágenes LCP externas o descubiertas tarde
- [ ] Probar prioridad en panel Network de DevTools
- [ ] Ejecutar Lighthouse antes y después
- [ ] Monitorear Core Web Vitals en Search Console
- [ ] Configurar RUM para rastrear mejoras LCP de usuarios reales
Artículos Relacionados
- Fetchpriority Explicado - Introducción al atributo fetchpriority
- Guía de Optimización LCP - Optimización completa de Largest Contentful Paint
- Mejores Prácticas de Lazy Loading - Cuándo usar y evitar lazy loading
- Guía de Optimización de Imágenes - Estrategias integrales de optimización de imágenes
Referencias
- web.dev - Optimize resource loading with the Fetch Priority API
- web.dev - Optimize Largest Contentful Paint
- Chrome Developers - LCP request discovery
- Chrome DevTools - Analyze runtime performance
- MDN Web Docs - HTMLImageElement: fetchPriority property