El coste de cada estrategia en cada métrica
La aritmética de la cadena crítica en SSG, SSR, ISR y CSR con supuestos explícitos, el reparto del presupuesto de LCP, y qué métrica no arregla ninguna estrategia.
La diferencia de rendimiento entre estrategias no se explica bien diciendo que una es más rápida que otra. Se explica contando eslabones: cuántas operaciones tienen que ocurrir en serie antes de que el usuario vea contenido. Renderizar en el cliente no es lento porque el navegador sea lento; es lento porque encadena seis pasos donde otras estrategias encadenan dos y paralelizan el resto. Esta lección hace esa aritmética con supuestos explícitos para que puedas rehacerla con los tuyos.
- Repartir el presupuesto de LCP entre sus cuatro subpartes con porcentajes concretos.
- Calcular la cadena crítica de cada estrategia con supuestos de red y CPU declarados.
- Explicar por qué el CLS y el INP no dependen de la estrategia de la misma forma que el LCP.
- Fijar un presupuesto por ruta a partir de la estrategia elegida.
Los umbrales y el reparto del LCP
Los umbrales de referencia, en el percentil 75 de las visitas reales:
| Métrica | Bueno | Malo |
|---|---|---|
| TTFB | hasta 800 ms | más de 1800 ms |
| FCP | hasta 1,8 s | más de 3,0 s |
| LCP | hasta 2,5 s | más de 4,0 s |
| INP | hasta 200 ms | más de 500 ms |
| CLS | hasta 0,1 | más de 0,25 |
El LCP se descompone en cuatro subpartes, y la guía de reparto que recomienda la documentación de Google para un objetivo de 2,5 segundos es esta:
| Subparte | Fracción del LCP | Con objetivo de 2,5 s |
|---|---|---|
| Tiempo hasta el primer byte | ~40 % | ~1000 ms |
| Retraso en descubrir el recurso | menos del 10 % | ~250 ms |
| Descarga del recurso | ~40 % | ~1000 ms |
| Retraso hasta pintarlo | menos del 10 % | ~250 ms |
Ese reparto es la herramienta de diagnóstico más útil del nivel, porque convierte “el LCP es malo” en “el LCP es malo por aquí”. Y explica de golpe por qué la estrategia de render importa tanto: dos de las cuatro subpartes —el primer byte y el retraso en descubrir el recurso— dependen directamente de ella.
La aritmética, estrategia por estrategia
Supuestos declarados, los mismos para las cuatro. Red de tipo 4G lento: 1,6 Mb/s de bajada y 150 ms de ida y vuelta, que es el perfil que usa Lighthouse por defecto para móvil. Conexión nueva con TLS 1.3 sobre TCP: dos idas y vueltas antes del primer byte de la petición, unos 300 ms. Dispositivo de gama media. Cambia los números por los tuyos y rehaz la cuenta; lo que importa es la estructura.
SSG desde un nodo de borde.
conexion 300 ms
peticion + respuesta del borde 150 ms (cache hit, sin computo)
--------------------------------------------
TTFB ~450 ms
descarga de HTML + CSS critico ~150 ms (en paralelo, el escaner ya vio todo)
FCP ~650 ms
descarga de la imagen del hero ~500 ms (empezada a los 450 ms)
LCP ~1.100 ms
La clave está en el paralelismo: el HTML llega con todo dentro, así que el escáner de precarga del navegador descubre la hoja de estilos, la fuente y la imagen del hero antes de haber terminado de analizar el documento, y las pide a la vez.
SSR con un servidor razonable.
conexion 300 ms
computo del servidor + consultas 250 ms
primer byte 150 ms
--------------------------------------------
TTFB ~700 ms
FCP ~900 ms
LCP ~1.400 ms
Idéntico a lo anterior más el tiempo de servidor. Todo lo que tarde el servidor se suma directamente al LCP del usuario, sin amortiguación posible. Un servidor que tarda 900 ms —lo cual es completamente normal con dos consultas y una plantilla— pone el TTFB en 1,35 s y hace matemáticamente imposible un LCP bueno con esa red.
ISR. En acierto de caché, idéntico a SSG. En fallo, idéntico a SSR más el coste de guardar. La cifra que hay que vigilar no es el tiempo medio sino la tasa de acierto: con un 95 % de aciertos, el percentil 75 se comporta como estático; con un 60 %, el percentil 75 ya está en territorio de servidor.
CSR.
conexion 300 ms
HTML vacio 150 ms
--------------------------------------------
TTFB ~450 ms <- excelente y no significa nada
descubrir y descargar el JS
200 KB comprimidos a 1,6 Mb/s 1.000 ms
analizar, compilar y ejecutar
~700 KB sin comprimir 600 ms <- en gama media; en gama baja, el doble
peticion a la API + respuesta 400 ms
construir el DOM y pintar 150 ms
--------------------------------------------
FCP y LCP ~2.800 ms
Fíjate en dónde está la diferencia. No es que ningún paso sea absurdamente lento: es que hay seis pasos en serie y en las otras estrategias hay tres. El HTML no puede empezar a descargar el JavaScript hasta que llega, el JavaScript no puede ejecutarse hasta que se descarga, la API no se puede pedir hasta que el JavaScript se ejecuta, y no hay nada que pintar hasta que la API responde. Cada eslabón espera al anterior.
Y ese es también el motivo de que las optimizaciones habituales de CSR den tan poco: dividir el paquete reduce un eslabón, pero la cadena sigue teniendo seis. Para cambiar de categoría hay que romper la serialización, y las dos formas de hacerlo son mandar el contenido dentro del HTML —cualquiera de las otras tres estrategias— o adelantar peticiones con pistas al navegador para que la API se pida antes de que el JavaScript exista.
Las métricas que la estrategia no arregla
El CLS depende poco de la estrategia y mucho de la disciplina. Los saltos vienen de imágenes sin dimensiones reservadas, de fuentes que cambian la métrica al cargar, de banners inyectados y de contenido que aparece por encima de lo que el usuario ya está leyendo. Una página estática con imágenes sin aspect-ratio tiene mal CLS. Una aplicación de cliente con esqueletos del tamaño exacto del contenido final puede tenerlo perfecto.
Hay un matiz donde sí influye: en CSR todo aparece de golpe cuando el JavaScript termina, y esa aparición masiva es una oportunidad enorme de salto. En estático el contenido llega ya colocado.
El INP no depende de la estrategia sino del JavaScript que se ejecuta al interactuar. Una página estática que carga un paquete de 400 KB de widgets tendrá peor INP que una renderizada en servidor que no carga casi nada. La correlación que la gente observa —que las webs estáticas suelen tener mejor INP— es real pero indirecta: quien elige estático suele enviar menos JavaScript.
Donde sí hay un efecto causal directo es en la ventana de hidratación, cuando la página se ve completa pero todavía no responde. Eso no es una propiedad de SSR: es una propiedad de SSR más un cliente que rehidrata, y tiene su lección propia en el impuesto de la hidratación.
El TTFB es el único suelo duro. Es la única métrica que ninguna técnica de cliente puede mejorar: es lo que tarda el primer byte en llegar, y todo lo demás ocurre después. Si tu TTFB en el percentil 75 es de 1,4 segundos, tienes 1,1 segundos para todo el resto del LCP, y eso no se consigue. Por eso el orden correcto de trabajo, cuando el LCP es malo, es siempre mirar el TTFB primero: es el único número que puede hacer imposible el objetivo por sí solo.
Si te quedas con una sola idea del nivel, que sea esta, porque se generaliza a cualquier problema de latencia y no solo a la web. Todas las estrategias hacen aproximadamente el mismo trabajo total: obtener datos, convertirlos en marcado, entregar el marcado, pintarlo. Lo que cambia radicalmente entre ellas es cuánto de ese trabajo puede solaparse. El navegador es una máquina extraordinariamente buena paralelizando: el escáner de precarga lee el HTML por delante del analizador principal y empieza a descargar la hoja de estilos, la fuente y la imagen del hero mientras el documento todavía está llegando; la decodificación de imágenes va en otros hilos; la compilación de JavaScript se solapa con la descarga. Todo ese paralelismo depende de una condición: que el navegador sepa qué necesita. Y solo lo sabe si se lo dicen en el HTML. Renderizar en el cliente es, exactamente, ocultarle al navegador qué recursos hacen falta hasta que un programa se haya ejecutado y lo decida. Le has quitado la información con la que paralelizaba, y por eso lo hace todo en fila. Escrito así se entiende también por qué las mejoras a CSR tienen tan poco recorrido: comprimir mejor el paquete, dividirlo en trozos o compilar más rápido reducen la duración de un eslabón, pero la cadena sigue siendo una cadena, y la longitud de una cadena la determinan las dependencias, no la velocidad de cada paso. Y se entiende por qué las técnicas que sí cambian de categoría —mandar el HTML con contenido, hacer streaming, emitir pistas de precarga en las cabeceras antes de calcular la respuesta— tienen todas la misma forma: adelantar información al navegador para que pueda empezar cosas antes. Ninguna hace nada más rápido. Todas hacen más cosas a la vez. La próxima vez que te enfrentes a un problema de latencia, en la web o fuera de ella, la pregunta productiva no es “¿qué paso puedo acelerar?” sino “¿qué información puedo adelantar para que dos pasos dejen de ser consecutivos?”.
Presupuesto por ruta
Con la aritmética anterior se puede escribir un presupuesto que significa algo, en vez de copiar los umbrales genéricos.
Para una ruta estática servida desde el borde, con TTFB de 450 ms, tienes 2.050 ms de margen hasta el LCP: sobra para una imagen de hero pesada y una fuente. El presupuesto debe ser exigente, del orden de 1,5 s de LCP objetivo, porque no hay excusa.
Para una ruta renderizada en servidor, el presupuesto empieza por el servidor: fija un objetivo de tiempo de respuesta del servidor y mídelo aparte, porque es lo único que puedes gestionar desde el backend y porque es lo que consume el presupuesto de todos los demás. Un objetivo razonable son 200 ms en el percentil 75, medido en el servidor, sin contar red.
Para una ruta de cliente, el presupuesto tiene que ser de bytes de JavaScript, no de tiempo, porque el tiempo es una consecuencia directa. Con los supuestos de arriba, cada 100 KB comprimidos de JavaScript cuestan medio segundo de descarga más unos trescientos milisegundos de análisis y ejecución en gama media. Eso convierte el presupuesto en una cuenta que cualquiera puede verificar en cada pull request, y esa verificabilidad es justo lo que hace que un presupuesto sobreviva; cómo se automatiza está en presupuestos que fallan el build.
- Mide tu TTFB real en el percentil 75 desde datos de campo y calcula cuánto margen te queda para el LCP.
- Descompón tu LCP en las cuatro subpartes y compara el reparto con los porcentajes de referencia.
- Cronometra el tiempo de servidor de tu ruta más lenta, sin contar red, y compáralo con el objetivo de 200 ms.
- Cuenta los eslabones en serie de tu ruta principal desde la petición hasta el primer píxel de contenido. Busca uno que puedas paralelizar.
- Convierte el peso de tu paquete de JavaScript a milisegundos con la aritmética de esta lección y verifica la estimación con una medida real en un móvil.