Saltar al contenido
Construcción, optimización y experimentos web[email protected]
La Trastienda WebLo que pasa detrás de una web
Experimentos

Presupuesto de rendimiento: cómo calcularlo con números

Un presupuesto de rendimiento convierte «que vaya rápido» en límites concretos. Cálculo paso a paso desde un LCP objetivo, reparto por recursos, anuncios y CLS, y archivos de configuración.

Por Redacción de La Trastienda WebPublicado el 9 min de lectura
Balanza de taller con bloques de colores que representan HTML, CSS, fuentes, JavaScript e imágenes frente a un cronómetro

«Que la página cargue rápido» no es un requisito: nadie puede comprobar si se cumple. Un presupuesto de rendimiento sí lo es. Web.dev lo define como un conjunto de límites sobre métricas que afectan al rendimiento: el peso total de la página, el tiempo de carga en una red móvil o el número de peticiones. La parte útil es que se puede calcular a partir de un objetivo y comprobar en cada cambio, antes de que una plantilla engorde sin que nadie lo note.

Tres tipos de límite

El artículo «Performance budgets 101» de web.dev distingue tres familias. Conviene combinarlas, porque cada una tapa los huecos de las otras.

Tipos de presupuesto de rendimiento
TipoEjemplosVentajaLimitación
Basado en tiemposLCP ≤ 2,5 s; TBT ≤ 200 ms en laboratorio móvilRefleja lo que vive el usuarioVaría entre ejecuciones; no dice qué recurso sobra
Basado en cantidades≤ 150 KB de JavaScript; ≤ 2 fuentes; ≤ 25 peticionesEstable, fácil de comprobar y de explicar a diseñoDos páginas del mismo peso pueden cargar muy distinto según el orden
Basado en reglas o puntuacionesPuntuación de rendimiento de Lighthouse ≥ 85Un solo número, con diagnósticos asociadosMezcla métricas y oscila varios puntos sin cambios reales

Criterio práctico: fija el objetivo en tiempos (LCP, porque es la Core Web Vital ligada a la carga; umbrales en LCP, INP y CLS), tradúcelo a cantidades para el día a día y usa la puntuación sólo como alarma secundaria, siempre sobre la mediana de varias ejecuciones (por qué, en Por qué PageSpeed Insights da una puntuación distinta cada vez).

Del objetivo de LCP a los kilobytes: el cálculo

La pregunta es: si quiero un LCP de 2,5 s en una conexión móvil modesta, ¿cuántos KB pueden viajar antes de que se pinte el elemento principal? Hace falta fijar una red. Aquí se toma la misma que Lighthouse usa por defecto para móvil según su documentación de limitación: 150 ms de latencia (RTT) y 1,6 Mbps de bajada. Es un supuesto; tus usuarios pueden estar mejor o peor.

Ejemplo de cálculo

Supuestos: RTT de 150 ms; 1,6 Mbps de bajada; servidor que tarda 200 ms en generar el HTML; HTTPS con TLS 1.3 sobre HTTP/2; todo servido desde el mismo origen; elemento LCP = una imagen.

1. Ancho de banda en bytes. 1,6 Mbps = 1.600.000 bits/s ÷ 8 = 200.000 bytes/s ≈ 200 KB por segundo.

2. Tiempo que se va en esperas, no en descargas.

  • DNS + conexión TCP + negociación TLS 1.3: unos 3 RTT = 3 × 150 = 450 ms.
  • Petición del HTML: 1 RTT (150 ms) + 200 ms de servidor = 350 ms.
  • El navegador encuentra CSS, fuente e imagen LCP al leer el HTML y las pide: al menos 1 RTT más = 150 ms (si la imagen sólo aparece referenciada en el CSS, súmale otro).
  • Margen para análisis, estilos, decodificación de la imagen y pintado en un móvil de gama media: 400 ms (estimación).

Total de esperas: 450 + 350 + 150 + 400 = 1.350 ms.

3. Tiempo que queda para transferir: 2.500 − 1.350 = 1.150 ms.

4. Bytes que caben: 1,15 s × 200 KB/s = 230 KB de techo teórico.

5. Ajuste realista. TCP no arranca a plena velocidad (arranque lento) y un segundo RTT para localizar recursos es habitual, así que conviene recortar un 25 %: 230 × 0,75 ≈ 170 KB comprimidos en la ruta crítica.

No es casualidad que la cifra se parezca a la que propone «Performance budgets 101»: menos de 170 KB de recursos de ruta crítica, comprimidos y minificados, como línea base razonable. Ese artículo es de 2018 y razonaba con otras métricas, pero el orden de magnitud sigue siendo útil.

Las cuentas son una aproximación de servilleta: Lighthouse no carga la página así, sino que simula la carga con su propio modelo, y tus usuarios reales no tienen todos la misma red. Sirven para decidir órdenes de magnitud (¿caben 170 KB o 700 KB?), no para predecir el LCP con precisión de décimas. Para confirmar, mide con método, como se explica en Cómo montar un experimento web.

Barra temporal de 2,5 segundos dividida en conexión 450 ms, HTML y servidor 350 ms, localización de recursos 150 ms, transferencia 1150 ms y render 400 ms
Con los supuestos del ejemplo, algo más de la mitad del objetivo de LCP se consume esperando; sólo 1,15 s quedan para descargar bytes.

Reparto del presupuesto por tipo de recurso

Con unos 170 KB críticos, el siguiente paso es repartirlos. Lo que no está en la ruta crítica (imágenes bajo el pliegue con loading="lazy", JavaScript diferido, anuncios cargados de forma asíncrona) va en una segunda columna con su propio techo, porque también consume datos y CPU, aunque no retrase el LCP del mismo modo.

Reparto ilustrativo para una página de artículo (tamaños transferidos, comprimidos)
RecursoRuta críticaResto de la cargaNº máx. de peticionesNota
HTML20 KB—1Comprimido con gzip o Brotli
CSS20 KB—1–2Bloquea el renderizado: cuanto menos, mejor
Fuentes30 KB20 KB2WOFF2 y subconjuntos; ver tipografías web
JavaScript propio30 KB70 KB3Diferido salvo lo imprescindible
Imagen LCP70 KB—1AVIF o WebP al tamaño mostrado
Otras imágenes—300 KB10Diferidas, con width y height
Terceros (anuncios, analítica)0 KBVer siguiente sección10Nunca antes del LCP
Total170 KB390 KB + terceros≈ 30

Las cifras son un punto de partida editorial, no una norma. Una tienda con galería necesitará más imagen y menos texto; un blog estático puede quedarse muy por debajo. Lo que importa es que la suma de la columna crítica no supere lo calculado.

Qué cambia al añadir anuncios

Los scripts de anuncios son el caso típico de presupuesto que se rompe sin tocar tu código: el peso y el JavaScript que llegan dependen de la red publicitaria y de la creatividad que gane cada subasta, y cambian de una carga a otra. Tres efectos a prever:

Ancho de banda

Supón que el conjunto de scripts y creatividades suma 150 KB (cifra ilustrativa; mídela en tu caso con la pestaña Red). A 200 KB/s, si compiten con la ruta crítica, son 0,75 s más de transferencia: con el cálculo anterior, el LCP pasaría de 2,5 s a unos 3,25 s. Por eso los scripts publicitarios se cargan con async y no deben retrasar la imagen principal.

Hilo principal

El JavaScript de terceros se ejecuta en el mismo hilo que el tuyo. En laboratorio se nota en TBT, la métrica que más pesa en la puntuación de Lighthouse (30 %); en campo, en INP. Reserva parte del presupuesto de JavaScript para ellos o, al menos, un límite de peticiones de terceros.

Espacio en pantalla y CLS

Un anuncio que aparece sin espacio reservado empuja el contenido hacia abajo. La guía de web.dev para optimizar CLS recomienda reservar el espacio en el diseño inicial, con min-height o aspect-ratio, y reconoce el dilema: reservar el tamaño máximo evita el salto pero deja hueco en blanco si llega un anuncio menor; reservar el tamaño más probable deja algún salto ocasional. Con min-height, a diferencia de height, un anuncio mayor puede mostrarse entero.

Ejemplo de cálculo: CLS de un anuncio sin espacio reservado

Supón una pantalla móvil de 400 × 800 px. El texto ocupa desde y = 300 hasta el final de la pantalla, a todo el ancho. Llega un anuncio de 250 px de alto justo encima y lo empuja.

La puntuación de un desplazamiento es fracción de impacto × fracción de distancia. La zona afectada va de y = 300 a y = 800 (antes y después del salto): 500 / 800 = 0,625. El contenido se mueve 250 px: 250 / 800 = 0,3125. Puntuación: 0,625 × 0,3125 ≈ 0,20, por encima del umbral de «bueno» (0,1).

Con min-height: 250px en el contenedor, el texto ya empieza en y = 550 y no se mueve: 0. Si llega una creatividad de 280 px, el texto baja 30 px: zona afectada 550–800, es decir, 250 / 800 = 0,3125; distancia 30 / 800 = 0,0375; puntuación ≈ 0,012. Asumible.

Dos móviles esquemáticos: a la izquierda un anuncio sin espacio reservado empuja el texto 250 px con CLS 0,20; a la derecha un hueco con min-height evita el salto y el CLS es 0
Reservar la altura del anuncio convierte un desplazamiento de 0,20 en cero, o en 0,012 si la creatividad es algo mayor de lo previsto.

Del papel a la configuración: budget.json y Lighthouse CI

Durante años, Lighthouse aceptó un archivo budget.json con la opción --budget-path. Su formato es un array de presupuestos; cada uno puede llevar path (a qué URLs se aplica, con sintaxis tipo robots.txt), timings (métrica y límite en milisegundos), resourceSizes (en KB) y resourceCounts. Los tipos de recurso válidos son document, font, image, media, other, script, stylesheet, third-party y total. Con el reparto anterior quedaría así:

[
  {
    "path": "/articulos/*",
    "options": { "firstPartyHostnames": ["www.example.com"] },
    "timings": [
      { "metric": "largest-contentful-paint", "budget": 2500 },
      { "metric": "total-blocking-time", "budget": 200 }
    ],
    "resourceSizes": [
      { "resourceType": "document", "budget": 20 },
      { "resourceType": "stylesheet", "budget": 20 },
      { "resourceType": "font", "budget": 50 },
      { "resourceType": "script", "budget": 100 },
      { "resourceType": "total", "budget": 560 }
    ],
    "resourceCounts": [
      { "resourceType": "third-party", "budget": 10 },
      { "resourceType": "total", "budget": 30 }
    ]
  }
]

En Lighthouse CI, los mismos límites se escriben como aserciones en lighthouserc.json. Los tamaños de resource-summary van en bytes, no en KB: es el despiste más común al migrar. Y puedes indicar que se evalúe la mediana de varias ejecuciones:

{
  "ci": {
    "collect": { "numberOfRuns": 5 },
    "assert": {
      "assertions": {
        "largest-contentful-paint": ["error", {"maxNumericValue": 2500, "aggregationMethod": "median"}],
        "total-blocking-time": ["warn", {"maxNumericValue": 200, "aggregationMethod": "median"}],
        "cumulative-layout-shift": ["error", {"maxNumericValue": 0.1, "aggregationMethod": "median"}],
        "resource-summary:script:size": ["error", {"maxNumericValue": 102400}],
        "resource-summary:total:size": ["warn", {"maxNumericValue": 573440}],
        "resource-summary:third-party:count": ["warn", {"maxNumericValue": 10}]
      }
    }
  }
}

102.400 bytes son 100 KiB y 573.440, 560 KiB, los mismos límites del budget.json. Las aserciones con error hacen fallar la comprobación; las de warn sólo avisan.

Ruta de decisión cuando el presupuesto se rompe

  1. ¿Se ha roto en la ruta crítica o en el resto? Si es en la crítica, el LCP está en juego: arréglalo antes de publicar.
  2. ¿Qué tipo de recurso ha crecido? Compáralo con la tabla de reparto. Si es la imagen LCP, recomprime o ajusta su tamaño; si es JavaScript, mira qué dependencia entró.
  3. ¿Aporta algo que el lector note? Si no, se quita. Si sí, se compensa recortando otra partida: el total no crece.
  4. ¿Hay que subir el presupuesto? Sólo con datos de campo que demuestren que el LCP real sigue por debajo del objetivo, y dejándolo anotado con fecha y motivo.

Cuándo no aplicar estas cifras tal cual

Si tu público está mayoritariamente en escritorio con fibra, la red del ejemplo es demasiado pesimista y el presupuesto puede ser más generoso; si está en zonas con redes lentas, quizá sea optimista. Si el elemento LCP es texto y no una imagen, la partida de imagen crítica desaparece y lo que pesa son CSS y fuentes. Y en una página que no aprueba Core Web Vitals por INP, recortar KB ayudará poco: el presupuesto que importa ahí es el de tiempo de ejecución de JavaScript. Rehaz el cálculo con tus supuestos; el método vale aunque los números cambien.

  • Objetivo de LCP elegido y red de referencia anotada como supuesto.
  • Cálculo de bytes críticos hecho con margen para arranque lento y RTT extra.
  • Reparto por tipo de recurso en una tabla que conozca todo el equipo.
  • Terceros fuera de la ruta crítica y con límite de peticiones.
  • Espacio de anuncios reservado con min-height por punto de corte.
  • Aserciones en Lighthouse CI con tamaños en bytes y mediana de varias ejecuciones.

Cómo se ha elaborado este artículo

El artículo se basa en el artículo «Performance budgets 101» de web.dev, en la guía de web.dev para optimizar CLS, en la documentación de limitación de red de Lighthouse, en las notas de la versión 12.0.0 de Lighthouse y en la referencia de configuración de Lighthouse CI. El cálculo del peso crítico es una estimación simplificada con supuestos explícitos (no reproduce el simulador de Lighthouse), y los repartos y tamaños de anuncio son ilustrativos. No incluye pruebas propias.

Fuentes consultadas

  1. web.dev: Performance budgets 101
  2. web.dev: Use Lighthouse for performance budgets
  3. web.dev: Optimize Cumulative Layout Shift
  4. GoogleChrome (GitHub): Lighthouse throttling
  5. GoogleChrome (GitHub): Release v12.0.0
  6. GoogleChrome (GitHub): Lighthouse CI configuration

¿Has visto un dato erróneo o desactualizado? Escribe a [email protected] indicando la URL. Las correcciones se aplican según la política editorial.