De 89 a 100 en Lighthouse: cómo llevé mi web al rendimiento máximo en una mañana
Esta mañana abrí PageSpeed Insights, escribí asturwebs.es y me encontré con un 89 de rendimiento en móvil. No estaba mal, pero no era suficiente. Dos horas después, tenía un 100/100/100 en rendimiento, accesibilidad y SEO.
No fue magia. Fue método. Te cuento qué hice, por qué funcionó, y qué aprendí.
Nota técnica: Lighthouse mide en “laboratorio” (simula 4G lento, CPU throttled). Para el ranking real, Google usa datos de campo de usuarios reales (CrUX). Un 100 en Lighthouse no garantiza que todos los usuarios vean lo mismo, pero demuestra que el sitio tiene el potencial óptimo. Y eso impacta positivamente en los datos reales.
El punto de partida
Mi web está construida con Astro 5 (HTML estático), React para componentes interactivos, y una API en Hono. Nada de WordPress, nada de PHP. A pesar de ser un site estático, Lighthouse me daba:
- Rendimiento: 89 — FCP 2.6s, LCP 3.2s, Speed Index 2.6s
- Accesibilidad: 96 — Problemas de contraste
- SEO: 92 — Enlace poco descriptivo
El diagnóstico fue claro: tres cosas bloqueaban el rendimiento.
Fix 1: Google Fonts te cuesta 750 milisegundos
Cargar la fuente Inter desde los servidores de Google adds tres requests: DNS, TLS y la descarga del CSS. En 4G lento, eso son 750 ms de render-blocking — el navegador no pinta nada hasta que resuelve la fuente.
Solución: Descargué los archivos woff2 de Inter (latin + latin-ext, solo lo que necesita una web en español) y los serví desde mi propio dominio.
Resultado: 750 ms de bloqueo → 0 ms. Y de paso eliminé dependencia de terceros.

Fix 2: Google Analytics se cargaba DOS veces
Este fue un error mío. Tenía GA en el <head> de Layout.astro (para todos los visitantes) Y en el componente CookieConsent (solo si aceptaban cookies). Resultado: 153 KiB de JS innecesario para usuarios que no habían aceptado cookies, y un problema de GDPR.
Solución: Eliminé el script de Layout y dejé solo el de CookieConsent, que carga GA únicamente tras el consentimiento.
Ahorro: 153 KiB de JS + 196 ms de hilo principal. Y ahora es legal.
Fix 3: El ChatWidget mataba el Speed Index
El componente ChatWidget.tsx usa React con useState, useEffect, useCallback… todo eso se hidrataba con client:load, lo que significa que el navegador lo descargaba y ejecutaba antes de pintar la página.
El chat pesa poco (~5 KiB), pero arrastra React entero (54 KiB). El problema no era el tamaño del archivo — era el coste de hidratación: la CPU del móvil pasaba 80ms “desempaquetando” React y evaluando el componente antes de permitir que el usuario hiciera scroll. Esos 80ms de Total Blocking Time (TBT) son tareas largas que congelan el hilo principal del navegador.
Solución: Implementé un patrón Facade. Creé un ChatWrapper.astro que renderiza un botón estático en HTML puro (0 JavaScript). Solo cuando el usuario hace clic, un import() dinámico carga React y el chat completo. El JavaScript se ejecuta en un momento de ocio del navegador, no durante el renderizado crítico.
<!-- Antes: React se hidrataba siempre, bloqueando el hilo principal -->
<ChatWidget client:load />
<!-- Después: HTML estático, React solo al hacer clic -->
<ChatWrapper /> <!-- botón HTML, 0 JS -->
El Speed Index bajó de 4.1s a 2.4s. El TBT pasó de 80ms a 0ms — la CPU del móvil ya no tiene que procesar React antes de mostrar la página.

Fix 4: Contraste WCAG — de 96 a 100 en accesibilidad
Lighthouse marcaba varios elementos con contraste insuficiente. La lección: el mismo color puede fallar en un fondo y pasar en otro. Hay que calcular contra el fondo real.
| Elemento | Antes | Después | Ratio | WCAG |
|---|---|---|---|---|
| Fechas blog (sobre blanco) | text-gray-400 (2.95:1) | text-gray-500 (5.74:1) | AA | |
| Footer (sobre gray-900) | text-gray-500 (3.67:1) | text-gray-400 (~7:1) | AAA | |
| Enlace cookies (sobre oscuro) | text-primary (2.2:1) | text-indigo-400 (5.1:1) | AA | |
| Badges servicios (sobre primary) | bg-white/20 (4.19:1) | border-white/40 (6.28:1) | AAA |
El caso de los badges es interesante: el fondo bg-white/20 aclaraba el indigo, reduciendo contraste con el texto blanco. Cambié a un borde semitransparente — el texto se compara contra el fondo original, no contra el badge.
Fix 5: Nginx no cacheaba .webp
Mi configuración de Nginx cacheaba png, jpg, svg… pero no .webp. El logo y todas las imágenes del blog se re-descargaban en cada visita.
Solución: Añadir webp y avif al regex de caché: 30 días, immutable.
El resultado


| Métrica | Antes | Después | Mejora |
|---|---|---|---|
| Rendimiento (móvil) | 89 | 100 | +11 |
| Accesibilidad | 96 | 100 | +4 |
| SEO | 92 | 100 | +8 |
| FCP | 2.6s | 1.2s | -54% |
| LCP | 3.2s | 1.4s | -56% |
| Speed Index | 2.6s | 2.4s | -8% |
| TBT | 80ms | 0ms | -100% |

Lo que aprendí
En un sitio estático, el rendimiento no se mejora con caché de servidor. Se mejora eliminando lo que bloquea el hilo principal del navegador. JavaScript innecesario, fuentes externas, hidratación prematura.
Cada byte de JS que quitas del renderizado inicial es un paso hacia el 100.
Y si tienes un componente interactivo que el 90% de los usuarios no va a usar en los primeros segundos, no lo cargues. Ponle una fachada estática y cárgalo cuando te lo pida.
Cómo evito que vuelva a bajar a 89
El rendimiento no es un destino, es un estado. Mi CI/CD en GitHub Actions builda y despliega automáticamente en cada push a main. Si un nuevo componente o un post pesado degrada las métricas, lo detecto en el siguiente deploy. La clave es que los patrones que he aplicado (self-hosting, facade, sin JS inicial) son estructurales — no dependen de un plugin que se actualiza y rompe todo.
¿Tu web está en la zona roja o naranja?
Cada segundo de carga te cuesta conversiones. Auditoría Lighthouse + plan de acción concreto.
Audita mi web →Preguntas frecuentes
¿Qué es Lighthouse y por qué importa para el SEO?
Lighthouse es la herramienta de Google que mide rendimiento, accesibilidad, SEO y buenas prácticas de una web. Google usa estas métricas como señal de ranking: una puntuación baja significa peor posicionamiento y más tasa de rebote.
¿Cuánto tiempo tarda en reflejarse una mejora de Lighthouse en el posicionamiento?
Las mejoras técnicas se detectan en días tras el rastreo de Googlebot, pero el impacto real en posiciones suele manifestarse en 2-6 semanas, especialmente si tu puntuación pasa de rojo/naranja a verde.
¿Self-hosting de fuentes mejora siempre el rendimiento?
Solo si tu hosting tiene buen TTFB y habilitas caché agresiva. Si usas un hosting lento, la fuente local será más lenta que la CDN de Google. En mi caso, con Nginx cacheando 30 días, pasó de 750ms de render-blocking a 0ms.
¿Qué es el patrón Facade y cuándo debo usarlo?
Consiste en renderizar un componente interactivo como HTML estático y solo cargar el JavaScript cuando el usuario interactúa. Es ideal para chatbots, reproductores de video, mapas o cualquier widget que la mayoría de usuarios no usará inmediatamente.