El coste de rendimiento de los frameworks JavaScript que nunca pones en la factura
El verdadero coste de rendimiento de un framework JavaScript no es la descarga, sino el tiempo de parseo en móviles baratos, la hidratación, la energía y años de churn. Así lo medimos.
El coste de rendimiento de los frameworks JavaScript que hunde un proyecto casi nunca es el que aparece en la insignia del tamaño del bundle. Los 45 kB comprimidos son la parte más barata, más visible y menos importante de la cuenta. Las partes caras son el tiempo de parseo y ejecución en un Android de cuatro años, el impuesto de hidratación que pagas en cada navegación, la energía que queman un millón de esas cargas de página, y el churn de mantenimiento que se come un día por trimestre para siempre. Esos costes no aparecen en ningún benchmark del README de un framework, así que casi nadie los contabiliza.
Nosotros sí, porque entregamos PHP renderizado en el servidor sin paso de build y aun así tenemos que justificar, por escrito, cada kilobyte de JavaScript de cliente que añadimos. Esta es la contabilidad que usamos.
La versión corta: qué significa de verdad "coste de rendimiento de un framework"
Cuando se dice que un framework es "rápido", normalmente se quiere decir una de dos cosas: renderiza rápido en una demo de dev-server en un MacBook, o su bundle comprimido es pequeño. Ninguna es el coste que le importa a un visitante real en un móvil real. El coste verdadero son cinco partidas:
- Peso de transferencia — bytes por la red. La única que mide todo el mundo.
- Tiempo de parseo y compilación — el coste de CPU de convertir ese JavaScript en código ejecutable, que escala con el móvil más lento de tu usuario, no con tu portátil.
- Ejecución e hidratación — correr el framework para "despertar" el HTML renderizado en el servidor, a menudo rehaciendo trabajo que el servidor ya hizo.
- Energía y carbono — los julios quemados en cada dispositivo que corre el código, multiplicados por el tráfico.
- Churn de mantenimiento — las horas-persona gastadas persiguiendo migraciones de versión mayor, deprecaciones y el árbol de dependencias que hay debajo.
Puedes tener un bundle minúsculo y aun así fallar en todos los demás. El peso de transferencia es el único coste trivial de resolver con un CDN y aquel con el que todo el mundo se obsesiona; los otros cuatro son donde los proyectos se pudren en silencio.
1. El peso del bundle es un señuelo
Cloudflare está delante de todos los sitios que mantenemos, así que un bundle de 200 kB de JavaScript se comprime, se cachea en el edge y llega en unas decenas de milisegundos para la mayoría de los visitantes. Si la transferencia fuera toda la historia, el peso del framework sería un error de redondeo.
No lo es, porque el recuento de bytes y el coste de esos bytes son monedas distintas. Una imagen de 100 kB y 100 kB de JavaScript no son equivalentes: el navegador decodifica la imagen fuera del hilo principal y se acabó. El JavaScript tiene que ser parseado, compilado y ejecutado en el hilo principal — el mismo hilo que gestiona toques, scrolls y renderizado. Los bytes de script son los bytes más caros que puedes enviar, y la insignia del bundle los cobra como si fueran los más baratos.
2. El tiempo de parseo y ejecución se mide en el dispositivo equivocado
Aquí está la partida que se salta. Parsear y compilar JavaScript es trabajo de CPU, y la CPU es el recurso que más varía entre los dispositivos que de verdad cargan tu sitio. Un visitante mediano no está en el portátil de la serie M donde se demostró el framework; una porción significativa está en un Android por debajo de los 200 € con dos o tres años, donde el motor de JS corre a una fracción de la velocidad.
Los mismos 300 kB de framework + código de aplicación que parsean en ~50 ms en una máquina de desarrollo pueden tardar varios cientos de milisegundos a más de un segundo en un móvil de gama baja, y ese tiempo se gasta en el hilo principal antes de que la página sea interactiva. Esta es la diferencia entre una puntuación de Lighthouse corrida en tu portátil y los datos de campo del Chrome User Experience Report. Hemos visto más de una vez cómo un "95 en el laboratorio" se convierte en una mueca bajo throttling en dispositivo real.
Nuestra regla: perfilar el trabajo pesado en JavaScript en Chrome DevTools con la CPU en throttling de 4x o 6x, en un perfil de red Slow 4G. Si no resulta cómodo ahí, no está terminado. El número del MacBook es marketing; el número con throttling es la verdad.
3. La hidratación es pagar dos veces por el mismo HTML
La hidratación es el paso en el que un framework de cliente toma el HTML renderizado en el servidor y le acopla sus propios event listeners y estado para que la página sea interactiva. La definición importa porque el coste es invisible en una captura de pantalla: la página parece lista mientras el framework recorre todo el árbol del DOM, reconstruye su representación virtual y vuelve a correr lógica de componentes que el servidor ya corrió.
En una página con mucho contenido esto es desperdicio puro. El servidor produjo HTML correcto y completo; la función de la hidratación es esencialmente hacer clicable un documento estático, y te cobra el coste total de renderizado una segunda vez en el cliente. Para un sitio de marketing, un caso de estudio, un artículo de journal — la mayor parte de lo que construye un estudio como el nuestro — no hay genuinamente nada que hidratar. El HTML es el producto.
Por eso nuestro default para contenido es no tener ningún framework de cliente. HTML renderizado en el servidor, un CDN, y unos pocos kilobytes de JavaScript vanilla escrito a mano para las dos o tres cosas que de verdad lo necesitan (un toggle de menú, el beacon de analítica, el lazy-loading de un embed de Matterport). Coste cero de hidratación porque no hay nada que hidratar. Cuando un proyecto necesita de verdad estado rico en el cliente — un configurador, la UI de recomendación que construimos para Jofit — recurrimos a islas: enviar interactividad solo a los componentes que la necesitan y dejar el resto como HTML estático.
4. El coste que nadie factura: energía y carbono
Cada milisegundo de parseo y ejecución es un dispositivo en algún lugar quemando electricidad. Una carga de página es insignificante. El tráfico a lo largo de la vida de un sitio no lo es. Si un framework añade 400 ms de trabajo de CPU por carga y una página se sirve unos pocos millones de veces al año, estás gastando julios reales en trabajo que el servidor podría haber hecho una sola vez.
Esto no es abstracto para nosotros — tenemos una disciplina de sostenibilidad y un montaje de analítica sin cookies precisamente para poder razonar sobre ello. La matemática del carbono es simple e incómoda: el JavaScript de cliente traslada la computación de un servidor bien gestionado a miles de dispositivos sin control, y no puedes optimizar hardware que no te pertenece. La petición más verde es la que llega como HTML terminado y solo le pide al dispositivo que lo pinte. Enviar menos script es la palanca de carbono web más eficaz que tenemos, y resulta ser la misma palanca que ayuda a los Core Web Vitals.
5. El churn de mantenimiento es un cargo recurrente
El coste que se compone es aquel al que te apuntas el día uno y pagas cada trimestre después. Un framework moderno arrastra un árbol de dependencias de cientos de paquetes transitivos, una toolchain de build, y una cadencia de versiones mayores a la que no le importa tu calendario de releases. Adóptalo y te has comprometido a migraciones, avisos de deprecación, breaking changes en herramientas que no elegiste, y un node_modules que tienes que seguir auditando en busca de vulnerabilidades.
Nuestra stack de PHP y vanilla tiene otro modo de fallo y somos honestos al respecto: escribimos más código a mano y no recibimos gratis el ecosistema de componentes de un framework. El intercambio que hicimos es que la plataforma de debajo — el lenguaje, las APIs del navegador — avanza en un horizonte de cinco a diez años, no de seis meses. El artículo de journal que estás leyendo se renderizará correctamente con cero mantenimiento durante años. La dependencia más barata de mantener es la que nunca añadiste.
Cómo se conecta esto con los Core Web Vitals
Los cinco costes de arriba mapean casi uno a uno con los Core Web Vitals de Google, las métricas de campo que miden la experiencia real del usuario:
- LCP (Largest Contentful Paint) sufre cuando el hilo principal está bloqueado parseando y ejecutando código de framework en lugar de pintar contenido.
- INP (Interaction to Next Paint), que reemplazó al FID en 2024, penaliza exactamente las tareas largas del hilo principal que crean la hidratación y la ejecución pesada. Aquí es donde el coste de parseo del móvil barato aparece como un número que Google reporta.
- CLS (Cumulative Layout Shift) empeora cuando el renderizado en el cliente reorganiza el contenido después de que el HTML del servidor ya haya pintado.
Nuestro objetivo es una puntuación de Lighthouse de 95 o más y — más importante — pasar los datos de campo del CrUX, no solo una corrida verde en el laboratorio. Lo logramos tratando el JavaScript de cliente como una responsabilidad a justificar y no como un default que se asume. La mayoría de las páginas que entregamos llevan kilobytes de script de un solo dígito. El framework más rápido es el código que no enviaste.
¿Entonces cuándo recurrimos a un framework?
Esto no es nihilismo de frameworks. Una aplicación compleja y con estado — un dashboard, un editor, una herramienta en tiempo real — es exactamente para lo que se construyeron los frameworks de cliente, y reimplementar una a mano en vanilla JS es su propio error caro. La cuestión es tomar la decisión con base en evidencia, no en costumbre.
La pregunta que hacemos en cada proyecto es simplemente: ¿cuál es el presupuesto de interactividad, y esta página lo gasta? El presupuesto de una página de contenido es casi cero, así que recibe casi cero JavaScript. El presupuesto de una aplicación es real, así que lo gastamos deliberadamente — e incluso entonces nos apoyamos en islas para que el framework solo corra donde el estado de verdad vive.
Contabiliza las cinco partidas antes de comprometerte, no solo la de la insignia. El tamaño del bundle es el precio de etiqueta. Tiempo de parseo, hidratación, energía y churn son el coste total de propiedad — y en un móvil real, sobre el terreno, a lo largo de la vida de un proyecto, esa es la cuenta que de verdad llega.