Este es un caso de estudio que podemos publicar con una confianza inusual, porque el paciente fue este mismo sitio web. En una sesión de trabajo llevamos nuestra página de inicio de un payload de 6.3 MB y un Largest Contentful Paint móvil de 34.6 segundos a 0.37 MB y 3.6 segundos — y la accesibilidad de 76 a 100. Aquí está exactamente qué estaba mal, qué cambiamos y qué medimos. Sin capturas de sitios ajenos; números propios.
La línea base (era mala)
| Métrica (móvil) | Antes | Después |
|---|---|---|
| Score de Performance | 50 | 76 (89 en desktop) |
| Largest Contentful Paint | 34.6 s | 3.6 s |
| Cumulative Layout Shift | 0.259 | 0 |
| Accesibilidad | 84 | 100 |
| Best Practices | 96 | 100 |
| Peso de la home | 6.3 MB | 0.37 MB |
Los números post-mejora son de laboratorio (Lighthouse, 4G simulado) contra el build de producción servido en local; los de campo en producción variarán.
Hallazgo #1: una imagen era el 82% de la página
El fondo del hero era un PNG de 5.14 MB y 2816 píxeles. Dos páginas hermanas cargaban PNGs de 9.4 MB y 6.8 MB propios — 21.5 MB de imágenes de hero en tres páginas. El arreglo es aburrido y vale más que todas las demás optimizaciones juntas: redimensionar al mayor ancho renderizado (1920px) y convertir a WebP. Resultado: 5.14 MB → 191 KB, visualmente indistinguible bajo el overlay oscuro del hero. Como la imagen era un background CSS — invisible para el preload scanner del navegador hasta que el CSS se parsea — añadimos <link rel="preload" as="image" fetchpriority="high">.
Hallazgo #2: el servidor mandaba todo crudo, siempre
El servidor web no tenía compresión ni cache headers: 550 KB de CSS/JS viajaban sin comprimir en cada visita. Activar gzip recortó el payload de texto ~75% (nuestra hoja de estilos más grande pasó de 89 KB a 14.5 KB en el cable), y los cache headers hicieron las visitas recurrentes casi gratis. Una advertencia que vale la pena robar: nuestras reglas de cache por regex habrían capturado en silencio rutas que deben proxearse a otro servicio — prefijar esos location con ^~ los blinda. Lo encontramos en pruebas, no en producción, que es el único lugar aceptable para encontrarlo.
Hallazgo #3: muerte por mil bloqueos de render
Una fuente de iconos entera cargada para exactamente un glifo (reemplazada por un SVG inline). Veinte variantes de webfonts declaradas, seis usadas. Tres scripts parseados sincrónicamente antes del primer paint (ahora defer). Un loader decorativo de pantalla completa que retenía la página 900 ms después de que todo ya había cargado. Y un widget residual de la plantilla que pedía un archivo eliminado del build — un 404 garantizado y error de consola en cada carga de cada página, que por sí solo costaba cuatro puntos de Best Practices.
Hallazgo #4: el layout shift se esconde en las buenas intenciones
Nuestra mayor lección de CLS: añadir atributos width/height a una imagen usando sus dimensiones intrínsecas empeoró las cosas, porque el CSS limitaba la altura renderizada — el header reservaba 165px, colapsaba a 40px y empujaba todo lo de abajo. Los atributos deben describir la geometría renderizada. El CLS pasó de 0.259 a cero.
Lo que deliberadamente no hicimos
Ninguna migración de framework, ningún build pipeline, ningún tree-shaking del bundle legado. La disciplina importa: el 90% de la ganancia vino de imágenes, compresión y headers — cambios con riesgo de regresión casi nulo. Los puntos móviles restantes viven en trabajo de critical-CSS cuyo riesgo/beneficio es una decisión aparte y consciente.
Ideas clave
- Pesa tu página antes de optimizar nada: un solo asset era el 82% de la nuestra.
- gzip + cache headers son un cambio de 30 minutos con retorno permanente.
- Los atributos width/height deben coincidir con la geometría renderizada, no la intrínseca.
- Medir, cambiar, volver a medir — y publicar tus números.
¿Trabajas en una industria regulada y peleas con los problemas descritos aquí? Construimos software exactamente para esto.
Habla con PBS