Ejemplo 06: Frames bloqueando LCP

← Volver al índice

LCP y el main thread

LCP (Largest Contentful Paint) mide cuándo se pinta el elemento más grande visible en el viewport. Es una métrica crítica de Core Web Vitals.

JavaScript que se ejecuta en el main thread puede bloquear o retrasar el LCP. Long Animation Frames API nos permite identificar exactamente qué scripts son los culpables.

Carga real con scripts bloqueantes

📊 LCP detectado:
Esperando carga...

Timeline de eventos:

Haz clic en uno de los botones para cargar la página

Análisis detallado:

¿Cómo los frames lentos afectan LCP?

1. Bloqueo del parser HTML

JavaScript síncrono bloquea el parser, retrasando el descubrimiento y renderizado del elemento LCP.

<!-- HTML -->
<script src="blocking.js"></script>  ← Bloquea
<img src="hero.jpg" />                ← LCP element (retrasado)

2. Bloqueo del render

Scripts que se ejecutan justo antes o durante el paint del LCP pueden retrasarlo.

3. Layout thrashing

Recálculos de layout fuerzan al navegador a retrasar el paint del LCP.

Detectar frames que bloquean LCP

1. Capturar el LCP

const lcpObserver = new PerformanceObserver((list) => {
  const entries = list.getEntries();
  const lastEntry = entries[entries.length - 1];

  console.log('LCP:', lastEntry.renderTime || lastEntry.loadTime);
});

lcpObserver.observe({
  type: 'largest-contentful-paint',
  buffered: true
});

2. Buscar LoAFs que ocurrieron antes del LCP

function findLcpBlockingFrames(lcpTime) {
  const loafs = performance.getEntriesByType('long-animation-frame');

  return loafs.filter(loaf => {
    // ¿El LoAF ocurrió antes del LCP?
    return loaf.startTime < lcpTime;
  });
}

3. Analizar el impacto

const blockingFrames = findLcpBlockingFrames(lcpTime);

blockingFrames.forEach(loaf => {
  console.log('Frame que bloqueó LCP:');
  console.log('  Duración:', loaf.duration);
  console.log('  Blocking:', loaf.blockingDuration);

  loaf.scripts.forEach(script => {
    console.log('  Script:', script.sourceFunctionName);
    console.log('  Tiempo:', script.duration);
  });
});

Umbrales de LCP

Rating Tiempo Interpretación
🟢 Bueno < 2.5s Experiencia rápida
🟡 Necesita mejora 2.5s - 4s Mejorable
🔴 Malo > 4s Experiencia lenta

Estrategias de optimización

Si encuentras frames bloqueando LCP:

✅ Diferir scripts no críticos
<script src="analytics.js" defer></script>
✅ Usar async para scripts de terceros
<script src="ads.js" async></script>
✅ Code splitting

Cargar solo el código necesario para el LCP, diferir el resto

✅ Server-side rendering (SSR)

El HTML ya incluye el contenido del LCP, menos JavaScript para bloquear

⚠️ Evitar:
  • Scripts síncronos grandes antes del LCP element
  • Layout thrashing durante la carga inicial
  • Fuentes web que bloquean el render (usar font-display: swap)