Guía detallada

Lcp Optimization Guide

Ver contenido

Guía Completa de Optimización de LCP: Técnicas Avanzadas para Tiempos de Carga Más Rápidos

Introducción

Largest Contentful Paint (LCP) mide cuándo el elemento de contenido más grande se vuelve visible para los usuarios. Aunque lograr una buena puntuación de LCP (menos de 2.5 segundos) puede parecer sencillo, optimizar LCP requiere entender los factores subyacentes y aplicar técnicas específicas.

Esta guía cubre estrategias de optimización avanzadas basadas en las recomendaciones oficiales de Google y datos de rendimiento del mundo real de millones de sitios web.

Entendiendo las Sub-Partes de LCP

Según la documentación de web.dev, LCP puede desglosarse en cuatro fases distintas. Entender estas fases es crucial para una optimización dirigida:

La Línea de Tiempo de LCP

Inicio de Carga → TTFB → Retraso de Carga de Recurso → Tiempo de Carga → Retraso de Renderizado → LCP

Presupuesto óptimo para objetivo de 2.5s:
├── TTFB:                       ~800ms (40%)
├── Retraso de Carga de Recurso: ~100ms (menos es mejor)
├── Tiempo de Carga de Recurso:  ~800ms (40%)
└── Retraso de Renderizado:      ~100ms (menos es mejor)

Fase 1: Time to First Byte (TTFB)

El tiempo desde el inicio de la navegación hasta que el navegador recibe el primer byte de HTML. Objetivo: Menos de 800ms.

Fase 2: Retraso de Carga de Recurso

El tiempo entre TTFB y cuando el navegador comienza a cargar el recurso LCP. Objetivo: Minimizar a casi cero.

Fase 3: Tiempo de Carga de Recurso

Cuánto tiempo tarda en cargar el recurso LCP (típicamente una imagen). Objetivo: Menos de 800ms.

Fase 4: Retraso de Renderizado del Elemento

El tiempo desde que el recurso carga hasta que se renderiza en pantalla. Objetivo: Minimizar a casi cero.

Optimizaciones del Lado del Servidor

1. Reducir TTFB

TTFB es la base de un buen LCP. Cada milisegundo ahorrado aquí fluye hacia la mejora de LCP.

Usa una CDN para assets estáticos:

Sin CDN:
Usuario (Chile) → Servidor (US) = 200ms latencia × 3 viajes = 600ms TTFB

Con CDN:
Usuario (Chile) → CDN Edge (Chile) = 20ms latencia × 3 viajes = 60ms TTFB

Habilita caché del lado del servidor:

# Nginx - Cachear assets estáticos
location ~* \.(jpg|jpeg|png|webp|gif|ico|css|js)$ {
    expires 1y;
    add_header Cache-Control "public, immutable";
}

# Cachear HTML para páginas estáticas
location / {
    add_header Cache-Control "public, max-age=3600, stale-while-revalidate=86400";
}

Usa HTTP/2 o HTTP/3:

# Configuración HTTP/2 en Nginx
server {
    listen 443 ssl http2;
    # HTTP/3 (QUIC) si está soportado
    listen 443 quic;
    add_header Alt-Svc 'h3=":443"; ma=86400';
}

2. Implementa Stale-While-Revalidate

Permite servir contenido cacheado mientras se obtiene contenido fresco en segundo plano:

Cache-Control: public, max-age=60, stale-while-revalidate=3600

Esto significa:

  • Servir contenido cacheado por 60 segundos
  • Después de 60 segundos, servir contenido obsoleto mientras revalida en segundo plano
  • El contenido se considera obsoleto pero usable hasta por 1 hora

Eliminar el Retraso de Carga de Recursos

El objetivo es hacer que el navegador descubra y comience a cargar el recurso LCP lo más temprano posible.

1. Precargar Imágenes LCP

Para imágenes que no son descubribles en el HTML inicial:

<head>
    <!-- Precarga con fetchpriority alto -->
    <link rel="preload"
          as="image"
          href="/images/hero.webp"
          fetchpriority="high">

    <!-- Para imágenes responsivas -->
    <link rel="preload"
          as="image"
          href="/images/hero.webp"
          imagesrcset="/images/hero-400.webp 400w,
                       /images/hero-800.webp 800w,
                       /images/hero-1200.webp 1200w"
          imagesizes="100vw">
</head>

2. Inlinear CSS Crítico

CSS bloquea el renderizado. Inlinea el CSS necesario para contenido above-the-fold:

<head>
    <!-- CSS crítico inlineado -->
    <style>
        /* Solo estilos necesarios para contenido above-the-fold */
        .hero {
            position: relative;
            min-height: 500px;
        }
        .hero-image {
            width: 100%;
            height: auto;
        }
    </style>

    <!-- Cargar stylesheet completo asíncronamente -->
    <link rel="preload" href="/styles/main.css" as="style"
          onload="this.onload=null;this.rel='stylesheet'">
    <noscript>
        <link rel="stylesheet" href="/styles/main.css">
    </noscript>
</head>

3. Evitar Lazy Loading en Elementos LCP

Según datos de HTTP Archive, el lazy loading de la imagen LCP es uno de los errores más comunes:

<!-- ❌ Error común: lazy loading de imagen hero -->
<img src="hero.webp" loading="lazy" alt="Hero">

<!-- ✅ Correcto: carga eager con prioridad alta -->
<img src="hero.webp"
     loading="eager"
     fetchpriority="high"
     decoding="async"
     alt="Hero">

4. Eliminar JavaScript que Bloquea el Renderizado

Mueve scripts no críticos al final o usa async/defer:

<!-- ❌ Bloquea renderizado -->
<script src="analytics.js"></script>

<!-- ✅ No bloquea renderizado -->
<script src="analytics.js" defer></script>

<!-- ✅ Carga en paralelo, ejecuta cuando está listo -->
<script src="analytics.js" async></script>

Cuándo usar cada uno:

  • defer: Scripts que necesitan DOM listo, ejecutan en orden
  • async: Scripts independientes como analytics, ejecutan inmediatamente al cargar

Optimizar el Tiempo de Carga de Recursos

1. Usar Formatos de Imagen Modernos

WebP y AVIF proporcionan reducciones de tamaño significativas:

<picture>
    <!-- AVIF: Mejor compresión, soporte limitado -->
    <source type="image/avif" srcset="hero.avif">
    <!-- WebP: Buena compresión, amplio soporte -->
    <source type="image/webp" srcset="hero.webp">
    <!-- JPEG: Fallback para navegadores antiguos -->
    <img src="hero.jpg" alt="Imagen hero">
</picture>

Ahorros típicos:

JPEG Original:     500KB (base)
WebP:              300KB (-40%)
AVIF:              200KB (-60%)

2. Implementar Imágenes Responsivas

Sirve imágenes del tamaño apropiado para cada viewport:

<img src="hero-800.webp"
     srcset="hero-400.webp 400w,
             hero-800.webp 800w,
             hero-1200.webp 1200w,
             hero-1600.webp 1600w"
     sizes="(max-width: 600px) 100vw,
            (max-width: 1200px) 80vw,
            1200px"
     alt="Imagen hero"
     width="1200"
     height="600"
     fetchpriority="high">

3. Usar CDN de Imágenes para Optimización Dinámica

Servicios como Cloudflare Images, imgix, o Cloudinary pueden optimizar imágenes al vuelo:

<!-- Redimensionamiento de Imagen Cloudflare -->
<img src="/cdn-cgi/image/width=800,format=auto,quality=80/hero.jpg"
     alt="Hero">

<!-- Dimensionamiento dinámico basado en viewport -->
<img src="/cdn-cgi/image/width=auto,format=auto/hero.jpg"
     sizes="100vw"
     alt="Hero">

4. Optimizar Carga de Fuentes para LCP de Texto

Si tu elemento LCP es texto, la carga de fuentes puede retrasarlo:

<head>
    <!-- Precargar fuente crítica -->
    <link rel="preload"
          href="/fonts/main.woff2"
          as="font"
          type="font/woff2"
          crossorigin>

    <!-- Usar font-display: swap -->
    <style>
        @font-face {
            font-family: 'MainFont';
            src: url('/fonts/main.woff2') format('woff2');
            font-display: swap;
        }
    </style>
</head>

Minimizar el Retraso de Renderizado del Elemento

1. Evitar CSS que Oculta Elementos LCP

Animaciones CSS o estados iniciales ocultos retrasan LCP:

/* ❌ Retrasa LCP - elemento comienza oculto */
.hero-image {
    opacity: 0;
    animation: fadeIn 0.5s forwards;
}

/* ✅ Mejor - elemento visible inmediatamente */
.hero-image {
    opacity: 1;
}

2. Reducir JavaScript que Modifica el Elemento LCP

El renderizado del lado del cliente que construye el elemento LCP lo retrasa:

// ❌ LCP retrasado hasta que JS ejecuta
document.getElementById('hero').innerHTML = '<img src="hero.webp">';

// ✅ Mejor - incluir elemento LCP en HTML
// Dejar que el navegador lo maneje nativamente

3. Usar Content-Visibility para Contenido Below-Fold

Previene que el contenido below-fold afecte el renderizado de LCP:

/* Saltar renderizado de contenido fuera de pantalla */
.below-fold-section {
    content-visibility: auto;
    contain-intrinsic-size: 0 500px;
}

Técnicas de Optimización Avanzadas

1. Priority Hints

Usa el atributo fetchpriority para señalar la importancia de recursos:

<!-- Alta prioridad para imagen LCP -->
<img src="hero.webp" fetchpriority="high" alt="Hero">

<!-- Baja prioridad para imágenes below-fold -->
<img src="footer-logo.webp" fetchpriority="low" alt="Logo">

<!-- Alta prioridad para script crítico -->
<script src="critical.js" fetchpriority="high"></script>

2. Early Hints (Código de Estado 103)

Envía hints sobre recursos críticos antes de la respuesta principal:

HTTP/1.1 103 Early Hints
Link: </styles/critical.css>; rel=preload; as=style
Link: </images/hero.webp>; rel=preload; as=image

HTTP/1.1 200 OK
Content-Type: text/html
...

3. Carga Especulativa

Pre-renderiza páginas que los usuarios probablemente visitarán:

<!-- API de Speculation Rules -->
<script type="speculationrules">
{
    "prerender": [
        {
            "where": { "href_matches": "/productos/*" },
            "eagerness": "moderate"
        }
    ]
}
</script>

Medición y Monitoreo de LCP

Pruebas de Laboratorio

# Lighthouse CLI
lighthouse https://ejemplo.com --only-categories=performance

# WebPageTest
webpagetest test https://ejemplo.com --location=ec2-sa-east-1

Datos de Campo (RUM)

// Librería Web Vitals
import {onLCP} from 'web-vitals';

onLCP(({value, element}) => {
    console.log('LCP:', value, 'Elemento:', element);
    // Enviar a analytics
    analytics.track('LCP', {
        value,
        element: element?.tagName,
        url: window.location.href
    });
});

Chrome DevTools

  1. Abre DevTools → pestaña Performance
  2. Marca la casilla “Web Vitals”
  3. Graba una carga de página
  4. Busca el marcador “LCP” en la línea de tiempo
  5. Pasa el cursor para ver qué elemento disparó LCP

Patrones Comunes de Optimización de LCP

Patrón 1: Página con Imagen Hero

<!DOCTYPE html>
<html>
<head>
    <link rel="preload" as="image" href="hero.webp" fetchpriority="high">
    <style>/* CSS crítico inlineado */</style>
</head>
<body>
    <img src="hero.webp"
         fetchpriority="high"
         loading="eager"
         width="1200" height="600"
         alt="Hero">
</body>
</html>

Patrón 2: Página con Mucho Texto (Blog)

<!DOCTYPE html>
<html>
<head>
    <link rel="preload" href="font.woff2" as="font" crossorigin>
    <style>
        @font-face {
            font-family: 'Article';
            src: url('font.woff2') format('woff2');
            font-display: swap;
        }
        h1 { font-family: 'Article', serif; }
    </style>
</head>
<body>
    <h1>Título del Artículo Que Es el Elemento LCP</h1>
</body>
</html>

Lista de Verificación: Optimización de LCP

Servidor y Red
├── [ ] TTFB menor a 800ms
├── [ ] CDN configurado para assets estáticos
├── [ ] HTTP/2 o HTTP/3 habilitado
├── [ ] Compresión (Brotli/Gzip) habilitada
└── [ ] Headers de caché configurados

Descubrimiento de Recursos
├── [ ] Imagen LCP precargada
├── [ ] CSS crítico inlineado
├── [ ] JS que bloquea renderizado eliminado
└── [ ] fetchpriority="high" en elemento LCP

Optimización de Recursos
├── [ ] Formatos de imagen modernos (WebP/AVIF)
├── [ ] Imágenes responsivas con srcset
├── [ ] Dimensiones de imagen especificadas
├── [ ] Fuentes precargadas con font-display: swap
└── [ ] Imagen LCP NO tiene lazy loading

Optimización de Renderizado
├── [ ] Sin CSS ocultando elemento LCP
├── [ ] Sin JS construyendo elemento LCP
├── [ ] content-visibility para below-fold
└── [ ] Scripts de terceros diferidos

Artículos Relacionados

Referencias

Este artículo fue mejorado usando fuentes autoritativas:

[1] web.dev: Optimize Largest Contentful Paint https://web.dev/articles/optimize-lcp Guía completa de Google para optimización de LCP cubriendo las cuatro sub-partes: TTFB, retraso de carga de recurso, tiempo de carga de recurso, y retraso de renderizado del elemento. Incluye técnicas específicas y presupuestos de tiempo para lograr buenas puntuaciones de LCP.

[2] web.dev: LCP Breakdown https://web.dev/articles/lcp#what-is-a-good-lcp-score Desglose detallado de las fases de LCP con asignaciones de tiempo recomendadas. Explica por qué el 40% del presupuesto de 2.5s debería ir a TTFB y tiempo de carga de recurso cada uno, con tiempo mínimo para retrasos.

[3] Chrome Developers: Resource Loading Optimization https://developer.chrome.com/docs/lighthouse/performance/uses-rel-preload Documentación técnica sobre preload hints, atributo fetchpriority, y Priority Hints API para optimizar la carga de recursos críticos que afectan LCP.

[4] HTTP Archive Web Almanac: Performance https://almanac.httparchive.org/en/2024/performance Datos de rendimiento de toda la industria mostrando cuellos de botella comunes de LCP en millones de sitios web, incluyendo tasas de adopción de técnicas de optimización y patrones de mejora del mundo real.


Nota: Este artículo es parte de nuestra serie de análisis SEO. Explora todos los artículos en el Hub de SEO de Rendimiento.


Fuentes: web.dev (Optimización de LCP), Chrome Developers, HTTP Archive Web Almanac

Artículos relacionados

Versión relacionada

Introducción

Lcp Explained

Largest Contentful Paint (LCP) es uno de los Core Web Vitals de Google—un conjunto de métricas que miden la experiencia real del usuario en tu sitio web

Hub de categoría

Hub

Performance Seo Hub

El rendimiento es un factor de ranking crítico e impacta directamente la experiencia del usuario

En la misma categoría

Guía detallada

Fcp Optimization Guide

First Contentful Paint (FCP) mide cuándo los usuarios ven por primera vez contenido en tu página

Guía detallada

Ttfb Optimization Guide

Time to First Byte (TTFB) es la base del rendimiento web—cada milisegundo de TTFB retrasa toda la carga de tu página