La hinchazón de JavaScript en 2024
(tonsky.me)- Se ha vuelto común que las páginas web descarguen JavaScript sin comprimir mucho más grande que el contenido real, aumentando la carga del navegador tanto en landing pages simples como en apps de trabajo
- La medición se hizo en Firefox sobre macOS, con extensiones y caché desactivadas, contando solo JavaScript para enfocarse en el costo de ejecutar código, excluyendo imágenes, video y estilos
- Wikipedia marcó 0.2MB, pero páginas aparentemente simples como Linear llegaron a 3MB, Zoom y Vercel a 6MB, y GitLab a 13MB, es decir, desde varios MB hasta dos dígitos
- En apps, Gmail mostró 20MB frente a FastMail con 2MB, una diferencia de 10x, y herramientas de chat y trabajo como Jira con casi 50MB y Slack con 55MB destacaron por su enorme volumen de código
- JavaScript no solo cuesta al descargarse: también implica costos de parseo, permanencia en memoria y ejecución, por lo que una arquitectura que requiere bundles gigantes para renderizar contenido pequeño afecta directamente el rendimiento y la batería
Método de medición y criterio de comparación
- El entorno de medición fue Firefox sobre macOS, asumiendo que en otros navegadores el panorama sería en general parecido
- Las condiciones fueron las siguientes
- Modo normal, no incógnito
- Todas las extensiones desactivadas
- Medición de solo JavaScript
- Tamaño sin comprimir
- Service Worker activado
- Carga en frío con caché desactivada
- El contenido se excluyó de la comparación porque varía mucho entre sitios
- El video de YouTube y los mensajes de texto de Slack son, por naturaleza, de tamaños distintos
- Se usó JavaScript como métrica común para comparar la complejidad de la interacción
- El punto clave es la cantidad de trabajo que el navegador debe asumir para parsear y ejecutar el código
- Como referencia, el propio blog tonsky.me se midió en 0.004MB
Landing pages y contenido estático
- En ejemplos de páginas comunes con algo de interacción, Wikipedia quedó en 0.2MB
- Otras landing pages más pesadas fueron
- Linear: 3MB
- Zoom: 6MB
- Vercel: 6MB
- GitLab: 13MB
- Estas cifras corresponden al tamaño de solo código JavaScript, excluyendo imágenes, video y estilos
- Incluso sitios que muestran texto estático descargan varios MB de JavaScript
- Medium: 3MB
- Substack: 4MB
- Quora: 4.5MB
- Pinterest: 10MB
- Patreon: 11MB
- Hay casos donde se usan bundles grandes de JavaScript para mostrar contenido que parecería viable incluso como página estática
Búsqueda y apps de interacción simple
- Las apps centradas en búsqueda se basan en ingresar consultas y mostrar listas de resultados, pero su tamaño de JavaScript no es pequeño
- StackOverflow: 3.5MB
- NPM: 4MB
- Airbnb: 7MB
- Booking.com: 12MB
- La búsqueda de Google, pese a ser una interfaz centrada en un campo de texto y una lista de enlaces, se midió en 9MB
- Incluso servicios con una UI de entrada simple usan varios MB de JavaScript
- Google Translate: 2.5MB
- ChatGPT: 7MB
- Independientemente de que la complejidad de ChatGPT esté del lado del servidor, al navegador le llegan 7MB de JavaScript
Servicios de medios y correo electrónico
- El tamaño de JavaScript en servicios de video fue el siguiente
- Loom: 7MB
- YouTube: 12MB
- Pornhub: 1.4MB
- En servicios de audio, SoundCloud y Spotify se midieron en alrededor de 12MB cada uno
- En correo electrónico, la diferencia se amplía mucho
- Google Mail: 20MB
- FastMail: 2MB
- Dentro de la misma categoría de email, FastMail usa 10 veces menos JavaScript que Google Mail
- Los 20MB de Google Mail son una cifra comparable con apps como Figma, que incluyen renderizado personalizado con C++/OpenGL
Herramientas de productividad y edición de documentos
- Las apps de productividad también tienen mucho JavaScript para tareas relativamente simples
- Todoist: 9MB
- Dropbox: 10MB
- 1Password: 13MB
- Trello: 13.5MB
- Discord: 21MB
- Dropbox usa más de 10MB para mostrar una lista de archivos en una carpeta, 1Password para una lista de contraseñas y Trello para mostrar tarjetas
- Los servicios de edición de documentos están en niveles de dos dígitos en MB
- Google Docs: 13.5MB
- Notion: 16MB
- Editar documentos sí implica funciones difíciles como mover el cursor y sincronizar, pero aun así el tamaño de JavaScript de estos servicios sigue siendo grande
Redes sociales y casos gigantes
- Las redes sociales suelen usar alrededor de 12MB de JavaScript para funciones como likes, feed y mensajería
- Twitter: 11MB
- Facebook: 12MB
- TikTok: 12.5MB
- Instagram: 16MB
- LinkedIn: 31MB
- LinkedIn, que incluye blog, plataforma, búsqueda, mensajería y funciones sociales, se midió en 31MB
- Algunos casos de webapps enormes están casi en una categoría aparte
- Jira: casi 50MB
- Slack: 55MB
- Slack es una app de chat que maneja listas de usuarios, mensajes y reacciones, pero descarga 55MB de JavaScript
- react.dev empieza con 2MB, pero se observó que su JavaScript sigue creciendo al hacer scroll repetidamente
- Como ejemplo, se pudo llevar hasta 100MB
- Según una actualización, en la experiencia normal de usuario el editor de código embebido se guarda en caché tras la primera carga y luego ya no genera tráfico de red visible
- Aun así, al hacer scroll podrían seguir parseándose, evaluándose e inicializándose 100MB de JavaScript
Qué significa tener 10MB de código
- En 2015, el tamaño promedio de una página web ya se estaba acercando a los 2.5MB de la versión shareware de Doom 1
- En 2024, Slack alcanzó 55MB solo en JavaScript, igualando el tamaño total de los recursos del Quake 1 original
- Puede parecer que 10MB de código ya es algo normal, pero si se asumen 65 caracteres por línea en promedio, eso equivale a unas 150 mil líneas
- Como ese código ya está minificado, en su forma original podrían ser más de 300 mil líneas
- Google Maps suele citarse como un caso representativo de SPA, pero se midió en 4.5MB, por lo que frente a las webapps modernas incluso parece pequeño
- En Figma es natural que el tamaño de descarga de JavaScript sea alto por la complejidad del frontend, pero Gmail está al nivel de Figma, LinkedIn en 1.5x y Slack en 2.5x
El costo que paga el navegador
- El problema no termina en el tamaño de descarga
- JavaScript debe ser parseado, mantenido en memoria y ejecutado por el navegador, lo que genera un costo continuo
- Si se toma como criterio que el contenido debería ser más grande que el código, una arquitectura que necesita JavaScript 1000 veces más grande para renderizar una entrada de blog de 10K caracteres resulta excesiva
- Como ejemplo positivo, se menciona que algunos sitios funcionan perfectamente con apenas 0.1MB de JavaScript
- En el mismo entorno web, GitLab se compara como un caso que necesita 13MB, es decir, más de unas 500 mil líneas de JavaScript, para mostrar una landing page estática
1 comentarios
Comentarios de Hacker News
Basta comparar cosas de 10 MB o 12 MB con Pornhub, de 1.4 MB, que sí se preocupa de verdad por el rendimiento.
Los sitios porno siempre fueron alta tecnología web de verdad y tenían buena ingeniería, a diferencia de las grandes empresas de “tech” de chiste.
Casi no recuerdo que arruinaran la UI/UX básica, la entrega de contenido o un diseño de sentido común.
Siento que, solo porque en las aplicaciones web reales recargar la página era un comportamiento no deseado, de pronto todo el mundo empezó a tenerle miedo a las recargas de página en los sitios web.
Trabajé 20 años con aplicaciones empresariales y vi sistemas creados antes de que yo naciera; creo que React fue el mejor frontend para reemplazar esas horribles UI cliente/servidor anteriores en ese tipo de sistemas.
Angular/Vue y demás van en la misma línea. Pero en páginas web comunes casi no hacen falta, salvo en casos como Gmail o Facebook, donde la interacción y las actualizaciones en tiempo real son el núcleo del producto.
Para sitios como Pornhub, PHP alcanza perfectamente, y lo mismo para la mayoría de los sitios web. Basta ver cuánta gente todavía prefiere HN u old.reddit.com, y creo que muchos también preferirían old.Facebook al nuevo Facebook más lento.
Popups, popunders, mandarte a sitios agregadores parecidos con contenido falso, abrir sitios de afiliados en vez del contenido, contaminar resultados de búsqueda, cosas así.
El porno no es una industria que impulse la tecnología tanto como dice la gente, la leyenda urbana de Betamax contra VHS tampoco es cierta, y decir que lideró la innovación en internet es una exageración.
Hay algunos actores que crean productos de alta calidad, pero no representan a toda la industria. Hay muchas granjas de enlaces, contenido de relleno, sitios clonados, publicidad engañosa y manipulación de resultados de búsqueda.
Que los sitios principales de hoy sean rápidos parece ser resultado de la competencia. Si la UX es mala, como abunda el porno gratis, el usuario se va enseguida a otro lado, así que tienen que optimizar para la retención.
Otros sitios web tienen incentivos distintos, como accionistas, proveedores de contenido, contratos exclusivos o posiciones monopólicas, así que no necesitan optimizar tanto la experiencia de usuario.
Se invierten incontables horas en optimizar todo tipo de cosas: entrega de video, transmisiones en vivo (antes Flash, ahora WebRTC), tamaño de página, etc.
Me pregunto por qué están mirando datos sin comprimir. Varios de los sitios dados como malos ejemplos, al comprimirse, quedan fácilmente por debajo de los 1.5 MB de GMaps.
Creo que las apps dinámicas como Spotify o GMail están bien si la navegación después de cargar la página es rápida.
Prefiero algo como Discord, que tarda unos segundos en actualizar al inicio, a GitLab, que te hace esperar hasta 2 segundos cada vez que haces clic.
Creo que la prioridad actual por el arranque en frío y el renderizado estático en algunos sitios más bien arruina la experiencia.
Como experimento, navega el árbol de archivos en GitHub: en mi dispositivo se siente mucho más ágil que otras partes de GitHub. Casualmente, esta es una de las pocas partes que no usa renderizado estático.
Hago clic en cientos de páginas de GitHub por día, y preferiría que me enviaran una gran cantidad de JavaScript una vez y la cachearan lo más posible, en vez de volver a bajar todo el footer cada vez que quiero ver una pipeline.
[1]: GMail y Spotify son solo ejemplos; en realidad no los uso.
Este problema aparece con frecuencia en debates sobre accesibilidad, porque hay una gran brecha de rendimiento de CPU entre iOS y Android, y si se consideran los dispositivos de gama baja que usa mucha gente, incluso hay teléfonos Android nuevos vendidos hoy que pueden ser más lentos que un iPhone de 2014.
Si los desarrolladores solo usan el iPhone más reciente o un Android flagship, es fácil que no vean cuánto impacta la hinchazón del código en el usuario promedio.
https://infrequently.org/2024/01/performance-inequality-gap-...
El caché reduce el costo en energía y tiempo de la descarga y la descompresión, pero no elimina el costo real de uso.
Como regla práctica personal, cuanto más grande es el JavaScript sin comprimir, más código termina ejecutando la CPU constantemente cuando mueves el mouse, presionas teclas o haces scroll.
Prefiero sacrificar un poco de eficiencia en tiempo para ganar eficiencia energética, y donde se pueda reemplazar por CSS prefiero algo estático antes que una animación bonita.
O quizá el problema verdaderamente mayor son los sitios que descargan más archivos ante varias acciones, no solo cuando un clic lleva la URL a otra página. Eso es hinchazón oculta y también es muy malo para el archivado.
Ojalá no usaran JavaScript para mostrar otra “página” mientras la URL de la barra de direcciones queda igual. Eso también es pésimo para el archivado.
Otra regla práctica es que, cuanto más grande es el JavaScript sin comprimir, menos probable es que una versión archivada del sitio funcione correctamente.
La semana pasada mi internet estaba lento y, al hacer clic en archivos en el sitio web de GitHub, intentaba cargarlos con scripts, fallaba, y el árbol de archivos literalmente no servía.
En cambio, si copiaba la URL del archivo y la pegaba en la barra de direcciones del navegador, cargaba bien.
Spotify tiene grandes problemas de conectividad de red. Aunque descargues un álbum, si cambia la red entra en pánico total. Es mejor simplemente usar modo offline que intentar mantenerse online todo el tiempo.
Es difícil juzgar toda esa arquitectura a partir de eso; sería parecido a señalar una SPA muy mala y decir que todas las SPA son malas.
Todo software refleja la forma de la organización que lo creó
Es muy probable que la mayor parte de los datos transferidos no sea JavaScript realmente necesario para el funcionamiento de la página, sino herramientas de analítica y todo tipo de scripts de terceros
Solo la categoría “elephant” corresponde a módulos con carga diferida como React
Gran parte de esto lo impulsan equipos de marketing que no conocen este problema o no les importa
Muchas veces los desarrolladores solo pegaron Google Tag Manager u otro servicio de inserción de scripts en la página. En algunos casos ni siquiera hicieron eso: un proxy en la infraestructura de operaciones modifica la página
Una preocupación más significativa podría ser que marketing tiene más control sobre el resultado que las personas que hacen el trabajo real
En el caso de las páginas “elephant”, la obesidad está en la organización misma. No es un problema de unos cuantos tontos, sino de tontos a escala
En mi trabajo anterior, un departamento no técnico tenía en sus manos Google Tag Manager, y teníamos que vigilar constantemente la basura que se inyectaba en las páginas de producción
Peleé muchísimo para eliminarlo
El Google de las búsquedas lo era más que Yahoo, y Chrome también lo era más que IE/Firefox cuando se lanzó
Chrome en sí casi no tenía interfaz, y esa era una característica
Acabo de volver de un road trip por Nueva Zelanda, y en muchas zonas rurales hay muy poca señal celular o directamente ninguna
Sumado al roaming, se siente como una capa más de lentitud, así que usar gran parte de la web fue realmente difícil
Si hay algún PM de Spotify, me gustaría que revisaran la UX sin conexión. El modo offline es una de las funciones clave de Premium, pero cuando intentas usar la app sin conexión, en la práctica es malísima en varios aspectos
Si Spotify decide que hay internet, le pregunta al servidor por todo el contenido de los menús contextuales, espera varios segundos una respuesta, y a veces abandona la idea de mostrar el menú, mientras que otras veces vuelve a la acción que habría sido inmediata si hubiera estado en modo offline
Detesto este reproductor
En estados intermedios con latencia muy alta o mucha pérdida, en la práctica debería comportarse como si estuviera offline, pero Spotify cree que está online
Dicho eso, este problema es muy común y no es algo en lo que solo falle Spotify; seguramente es difícil definir los umbrales correctos
No entiendo por qué Spotify me hace esperar 30 segundos para que la app cargue algo cuando no hay señal. Solo quiero seguir escuchando un podcast que ya descargué
Me da curiosidad qué decisión de ingeniería hizo tan complicado ponderar este tipo de escenarios
Este artículo pasa completamente por alto, en particular, el hecho de que no descompone por qué los archivos JavaScript son tan grandes en aplicaciones web reales
Por ejemplo, si se mira en detalle, Google Translate no es una app en la que interactúas una vez y listo. Tiene diccionario, sugerencias alternativas, transliteración, pronunciación, múltiples métodos de entrada, etc.
Aun considerando eso, 2.5MB es demasiado, y creo que algunas funciones opcionales podrían y deberían cargarse de forma diferida, pero el artículo actual es demasiado flojo como para aportar mucho a una discusión más profunda
¿Cuánto JavaScript puede hacer falta para
if data.transliteration show icon with audio embed?Entiendo que las imágenes podían ser grandes y numerosas, pero fue un poco irónico
Entiendo que la implicación aquí es “hay demasiado JavaScript”, pero también habría que hablar de qué parte de todo esto es pura basura de rastreo
Lo peor es que algunas no vienen empaquetadas con el código del host, sino que se traen desde afuera, lo que aumenta la latencia y los riesgos potenciales de seguridad
Era una herramienta que permitía a los marketers inyectar cualquier basura en una aplicación web sin intervención de desarrolladores
Las relaciones se dañaron un poco, no gané, y el rendimiento sigue siendo pésimo
Lo siguiente que causa problemas de rendimiento son bibliotecas pesadas como mapas y gráficos, y normalmente se resuelve con una carga diferida inteligente
Entre las cosas que viví directamente: una función muy pequeña que, aun así, cargaba al inicio una biblioteca de escaneo de códigos QR y una de mapas; todos los strings de internacionalización solicitados al inicio en cascada, bloqueando antes de que pudiera ejecutarse cualquier JS; y Zendesk arruinando por completo el rendimiento de la página, pero como venía por orden de arriba, solo se le pudo aplicar carga diferida
Después viene el código mal diseñado que provoca demasiados elementos del DOM, rerenderizados o solicitudes en cascada
Por último está el tamaño del código a nivel de app, que también se puede corregir con carga diferida, pero normalmente no hace falta hasta que la aplicación se vuelve enorme
Por ejemplo, la landing page de GitLab pasó de 13MB a “apenas” 6MB al bloquear los scripts de rastreo
El departamento de marketing siempre duplicará la obesidad del software
Comparación de cuánto JavaScript cargan sitios populares en una carga en frío. Los puntos principales son los siguientes:
PornHub carga aproximadamente 10 veces menos JS que YouTube (1.4 MB vs. 12 MB).
Gmail tiene un footprint difícil de entender por lo grande (20 MB). Fastmail es 10 veces más ligero, con 2 MB, y Figma ronda los mismos 20 MB pese a ser una app más compleja.
Jira llega a 58 MB, una barbaridad.
Jira, una vez descargado, probablemente se cargue localmente como una app offline hasta la próxima actualización.
Pornhub probablemente se use en modo incógnito, así que la caché no ayuda.
Jira también es terrible y lento.
Todas las páginas de https://wordsandbuttons.online/ siguen estando por debajo de 64 KB, aunque tengan animaciones e interacción.
Por ejemplo, esta página https://wordsandbuttons.online/trippy_polynomials_in_arctang... pesa 51 KB.
El código tampoco es nada económico. El 80% es copy-paste con pequeñas variaciones, y no hay ningún intento ingenioso de reducirlo. Todo es vanilla JS viejo, sin compresión ni minificación.
Si se abre con “View page source”, el código se puede leer perfectamente.
El secreto es una política de cero dependencias. No hay dependencias de terceros ni internas. Todo el código necesario viene junto con el archivo HTML.
Paradójicamente, a largo plazo el copy-paste no es la causa de la hinchazón, sino una forma de prevenirla.
En móvil, los bordes literalmente no se ven.
Las dependencias en sí no son la causa, sino un síntoma. Como los sitios web y las empresas ya no tienen incentivos para reducir la hinchazón, las dependencias duplicadas casi nunca se limpian.
Me recuerda al artículo The Website Obesity Crisis de 2015 [1]. Desde entonces [2] la situación empeoró, y ya pasaron casi 10 años.
¿Sería una tontería decir que dentro de 10 años navegar la web en una PC de alrededor de 2015 será imposible? Si nada cambia, eso parece.
Incluso con el Firefox más reciente en una MacBook vieja de 2013, no puede con los 23.98 MB de JavaScript de una página de https://civitai.com, y se queda congelada unos 30 segundos intentando renderizar ese desastroso frontend web.
No es solo un problema de la web. Las apps móviles todo-en-uno también se volvieron tan grandes que tampoco cargan en un teléfono de 2013, y la mitad de ellas están escritas sobre stacks de tecnologías web.
No entiendo por qué las empresas con grandes presupuestos no pueden permitirse usar aplicaciones nativas.
[1] https://idlewords.com/talks/website_obesity.htm
[2] https://hn.algolia.com/?dateRange=all&page=0&prefix=true&que...
El estado de la web da mucha tristeza.
La mayoría de la gente con conexión de fibra ni siquiera nota lo lenta que se volvió la web.
Pero si todavía estás con una conexión de 2 Mbps, es realmente horrible. Yo estoy en esa situación, y duele.
Por eso, no usar bloqueadores de anuncios/rastreo ni siquiera es una opción.
Me gustaría ver esta prueba con Ublock Origin activado.
Sospecho que la mayor parte de ese código es para rastrear usuarios y gestionar anuncios.
No entiendo si la idea es que, aunque tengamos computadoras mejores y más rápidas y redes más veloces, deberíamos seguir enfocándonos en hacer apps y sitios web cada vez más pequeños.
Gracias a la ley de Moore, los desarrolladores pudieron sacrificar optimización, empujar más cosas y moverse rápido; y eso pasa mucho.