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
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