Core Web Vitals a fondo: LCP, INP y CLS
Las tres métricas con que Google encuadra la experiencia de carga: qué mide cada una, qué la empeora y cómo la arquitectura de Astro las favorece por diseño. LCP y el elemento mayor, INP como sucesor de FID y su vínculo con el JavaScript, CLS y el salto de layout, y cómo medir de forma fiable en laboratorio y en campo con Lighthouse y PageSpeed Insights.
Los Core Web Vitals son el idioma común con el que la industria mide la experiencia percibida de una web: no la velocidad abstracta, sino cómo se siente cargar y usar una página. Son tres —LCP, INP y CLS— y cada uno captura un modo distinto de fallar: tardar en mostrar lo importante, tardar en responder al dedo, o moverse bajo la vista. Lo notable es que la arquitectura de Astro está alineada con estas métricas por construcción: enviar HTML y casi nada de JavaScript no es un truco para aprobar el examen, es la causa de aprobarlo.
- Entender qué mide
LCPy qué retrasa el elemento mayor. - Entender
INPcomo sucesor deFIDy su vínculo con el JavaScript. - Entender
CLSy las causas del salto de layout inesperado. - Medir con fiabilidad en laboratorio y en campo con las herramientas correctas.
LCP: pintar pronto lo que importa
LCP —Largest Contentful Paint— mide cuánto tarda en dibujarse el elemento de contenido más grande visible al cargar: normalmente una imagen de cabecera, un bloque de texto destacado o un vídeo. Es el momento en que el visitante siente que la página ya está. Se considera bueno por debajo de 2,5 segundos.
Lo empeoran cuatro cosas: un TTFB alto porque el servidor tarda en responder, recursos que bloquean el render como CSS o fuentes, imágenes pesadas o sin prioridad, y recursos que el navegador descubre tarde en el HTML. Astro ataca la raíz de casi todas: entrega HTML estático que se pinta sin esperar a hidratar nada, su componente de imagen sirve formatos modernos con el tamaño justo, y no interpone un runtime de framework entre la respuesta y la primera pintura.
---
import { Image } from 'astro:assets';
import heroe from '../assets/heroe.jpg';
---
<!-- priority marca el LCP: lo precarga y no lo difiere -->
<Image src={heroe} alt="Portada" priority />
El atributo priority hace dos cosas a la vez: precarga la imagen para que el navegador la descubra cuanto antes y desactiva su carga diferida, declarando que es el recurso más importante de la pintura inicial. Reservar esa prioridad para el elemento del LCP —y solo para él— es una de las palancas más directas de la métrica.
INP: responder sin demora
INP —Interaction to Next Paint— sustituyó en 2024 a FID como métrica oficial de respuesta. Mientras FID solo medía la primera interacción, INP observa todas a lo largo de la visita y refleja la peor experiencia representativa: el tiempo entre que tocas algo y la pantalla responde. Se considera bueno por debajo de 200 milisegundos.
Su causa dominante es el JavaScript. Cuando el hilo principal está ocupado ejecutando tareas largas —hidratar una isla enorme, correr el manejador de un evento pesado—, no puede atender el toque del usuario, y esa espera es INP. Aquí el modelo de islas de Astro rinde de forma estructural: al enviar menos JavaScript y trocearlo en unidades pequeñas que se hidratan por separado, el hilo principal tiene menos tareas largas y responde antes. La página que no ejecuta apenas nada responde casi al instante.
INP no cronometra solo cuánto tarda el navegador en empezar a atender un evento, sino el ciclo completo hasta la siguiente pintura: procesar el evento, correr sus manejadores y volver a dibujar. Por eso un manejador que hace demasiado —recalcular, reordenar el DOM, disparar trabajo síncrono— penaliza aunque el hilo estuviera libre al empezar. Mantener los manejadores ligeros y aplazar el trabajo no urgente es tan importante como reducir la hidratación inicial.
CLS: no moverse bajo la vista
CLS —Cumulative Layout Shift— mide cuánto se desplaza el contenido de forma inesperada mientras la página carga. Es la métrica de la frustración: el botón que se mueve justo cuando vas a pulsarlo, el texto que salta porque encima apareció una imagen. Se considera bueno por debajo de 0,1.
Las causas son concretas y evitables: imágenes o vídeos sin dimensiones declaradas, contenido inyectado por encima de lo ya visible, fuentes web que cambian el alto del texto al cargar, y —muy relevante en Astro— islas client:only que aparecen de golpe al hidratarse sobre un hueco vacío. El componente de imagen de Astro previene el primer caso reservando el espacio con el ancho y alto reales; el resto está en tu mano.
Conviene una precisión que ahorra falsos miedos: CLS solo cuenta los desplazamientos inesperados. Un cambio que sigue de cerca a una acción del visitante —desplegar un acordeón, abrir un panel— queda excluido dentro de una ventana breve, porque lo provocó él y lo esperaba. La métrica castiga la sorpresa, no el movimiento: por eso reservar el sitio de lo que aparece solo pesa tanto, mientras que animar algo que el usuario pidió no cuenta en su contra.
---
import Widget from '../components/Widget.jsx';
---
<!-- Reserva el alto para que la isla no empuje al montar -->
<div style="min-block-size: 240px">
<Widget client:only="react" />
</div>
client:visible y client:only mejoran el JavaScript, pero pueden empeorar el CLS si la isla ocupa más alto una vez montada que el hueco que dejaba antes. La solución no es renunciar a diferir, sino reservar el espacio con CSS —una altura mínima, una relación de aspecto— para que el contenido que llega después no empuje a nada. Rendimiento de carga y estabilidad visual no se contraponen si reservas de antemano el sitio de lo que va a aparecer.
Medir: laboratorio y campo
Hay dos mundos de medición y confundirlos lleva a conclusiones falsas. El laboratorio es una prueba sintética en un entorno controlado —Lighthouse en tu máquina o en tu CI, o la pestaña de rendimiento del navegador—: reproducible y útil para depurar, pero con un solo dispositivo y una sola red. El campo son datos de visitantes reales, que Google recoge en el CrUX y que PageSpeed Insights muestra junto al análisis de laboratorio.
# Laboratorio local, reproducible, ideal para CI
npx lighthouse https://mi-sitio.dev --view
La distinción es decisiva para dos métricas. INP y CLS dependen de la interacción y del recorrido real, así que el laboratorio los estima pobremente: solo el campo revela cómo responde tu página cuando gente distinta la usa en dispositivos distintos. Para capturar Web Vitals reales desde tu propio código, la librería web-vitals mide cada métrica en el navegador del visitante y te la envía.
import { onLCP, onINP, onCLS } from 'web-vitals';
onLCP(console.log);
onINP(console.log);
onCLS(console.log);
Cuando el LCP es alto y no sabes por qué, la pestaña de rendimiento del navegador lo desglosa en su cascada: cuánto tiempo se fue en TTFB, cuánto en descubrir y descargar el recurso del elemento mayor, y cuánto en pintarlo una vez llegó. Ese desglose te dice dónde intervenir —acelerar el servidor, precargar la imagen, desbloquear el render— en lugar de adivinar. Una métrica agregada señala el problema; su cascada señala la causa concreta que hay que atacar.
Lo profundo de estas tres métricas no es su fórmula, sino la decisión conceptual que encarnan: medir el rendimiento desde el lado del usuario y no desde el del sistema. Durante décadas se optimizó lo que era fácil de medir en el servidor —milisegundos de respuesta, peticiones por segundo— porque era lo que el operador veía en sus gráficas. Pero al humano frente a la pantalla no le importa cuántas peticiones por segundo aguanta tu máquina; le importa cuándo aparece lo que vino a ver (LCP), cuándo puede tocar algo y obtener respuesta (INP) y si lo que mira se queda quieto (CLS). Los Core Web Vitals trasladan la definición de rendimiento desde la eficiencia de la máquina hasta la experiencia de la persona, y esa mudanza reordena todo. Explica por qué Astro, que nunca fue el framework de los benchmarks de servidor más vistosos, domina precisamente estas métricas: porque su tesis —que la mayoría de la web es contenido y debe entregarse como HTML— coincide punto por punto con lo que un humano percibe como rápido. Enviar HTML pintado desde el primer byte favorece LCP; no ejecutar apenas JavaScript deja el hilo libre y favorece INP; reservar el espacio de cada pieza favorece CLS. No es que Astro haga trampas para aprobar el examen: es que el examen, por fin, pregunta lo que Astro siempre respondió bien. Y ahí está la lección que trasciende al framework: optimizar para métricas centradas en el usuario no es perseguir una nota, es alinear tus decisiones técnicas con la única definición de rápido que importa, la de quien está del otro lado esperando.
Los umbrales y el percentil 75
Las cifras de referencia —2,5 s, 200 ms, 0,1— no se juzgan sobre una visita, sino sobre la distribución de todas. Google evalúa cada métrica en el percentil 75 de tus visitantes reales: una página aprueba si el 75 por ciento de las sesiones queda por debajo del umbral. Esa elección es deliberada y tiene consecuencias.
Significa que no basta con que la página vuele en tu portátil rápido con fibra: tiene que ir bien también para el cuartil más desfavorecido, el de los dispositivos modestos y las redes lentas. Cada métrica se reparte además en tres bandas, y el objetivo es que la banda buena cubra a esa mayoría del percentil 75.
- Buena: el visitante no percibe fricción; la experiencia se siente inmediata.
- Necesita mejora: hay una demora perceptible que conviene atacar.
- Deficiente: la fricción es evidente y penaliza la experiencia y el posicionamiento.
Optimizar para el percentil 75 reordena las prioridades: dejas de perseguir el caso medio y empiezas a proteger el caso desfavorable, que es justo donde se pierden de verdad los visitantes.
LCP bajo 2,5 s
Pinta pronto el elemento mayor. HTML estático, imagen con priority y TTFB bajo lo favorecen.
INP bajo 200 ms
Responde al toque sin demora. Menos JavaScript y manejadores ligeros liberan el hilo principal.
CLS bajo 0,1
No te muevas bajo la vista. Dimensiones en imágenes y espacio reservado para islas diferidas.
Campo y laboratorio
Lighthouse depura; PageSpeed y CrUX revelan la realidad. INP y CLS solo se ven bien en campo.
flowchart TB U[experiencia percibida] --> LCP[LCP pintar lo mayor] U --> INP[INP responder al toque] U --> CLS[CLS estabilidad visual] LCP --> C1[TTFB alto o imagen pesada] INP --> C2[tareas largas de JavaScript] CLS --> C3[sin dimensiones ni espacio reservado] C1 --> A1[HTML estatico e Image con priority] C2 --> A2[islas pequenas y menos hidratacion] C3 --> A3[reservar alto y aspecto con CSS] style U fill:#f9e2af,color:#11111b style A1 fill:#a6e3a1,color:#11111b style A2 fill:#a6e3a1,color:#11111b style A3 fill:#a6e3a1,color:#11111b
- Pasa Lighthouse a una página tuya y anota
LCP,INPyCLS; identifica qué elemento es el que marca elLCP. - Consulta esa misma URL en PageSpeed Insights y compara los datos de campo con los de laboratorio: fíjate en dónde difieren.
- Provoca un salto de layout quitando las dimensiones de una imagen, mídelo, y arréglalo con el componente
Imageo reservando el espacio. - Instala la librería
web-vitalsen una página con una isla pesada y observa cómo empeora elINPal interactuar mientras se hidrata.