HTTP/2, HTTP/3 y minificación: ¿sigue valiendo la pena minificar?

HTTP/2, HTTP/3 y minificación: ¿sigue valiendo la pena minificar?

HTTP/2 y HTTP/3 cambian el trayecto de los archivos, no su peso. Mediciones de tamaño, compilación y bundling muestran lo que la minificación aún aporta.

22.10.2026
17 min de lectura
Compartir este artículo:
HTTPMinificaciónCompresiónRendimientoBundle

HTTP/2 cambió el trayecto de los archivos, no su peso

Una afirmación vuelve una y otra vez: desde que HTTP/2 multiplexa las peticiones, ya no haría falta minificar ni agrupar archivos. La mitad es cierta. El protocolo eliminó el coste de muchas peticiones pequeñas. No quitó ni un solo byte a un archivo JavaScript, y el navegador sigue teniendo que descargar, descodificar y compilar cada uno. Esta guía separa lo que HTTP/2 y HTTP/3 cambiaron de lo que dejaron intacto. Las cifras salen de tres pruebas del 22 de octubre de 2026 (el conjunto de datos de FastMinify, un paquete de 644 módulos y una prueba de compilación en V8). Las RFC y la documentación de los navegadores que se citan en el texto completan los hechos. Para la parte de compresión, consulta nuestra guía de GZIP y Brotli.

HTTP/2 y HTTP/3 cambian cómo se transportan las peticiones, no el tamaño de los archivos que llevan dentro.
En 10 bibliotecas JavaScript sin minificar, la minificación sigue quitando cerca de la mitad de los bytes gzip y brotli.
En CSS la ganancia tras la compresión baja a un 6 % aproximado, así que el argumento es más débil.
644 módulos diminutos se comprimen 2,4 veces peor que el mismo código en un archivo.
V8 compiló las bibliotecas minificadas entre un 7 % y un 37 % más rápido, es decir, de 0,1 a 1,2 ms por biblioteca en un portátil rápido.
El push del servidor, el sharding de dominios y un único archivo para todo el sitio son los hábitos que conviene abandonar.

Lo que cambiaron los protocolos y lo que dejaron intacto

HTTP/2 transporta muchas peticiones por una conexión

HTTP/2 (RFC 9113, junio de 2022) transporta muchas peticiones y respuestas a la vez por una sola conexión. Con HTTP/1.1, un navegador abría normalmente seis conexiones por host y ponía el resto en cola. Esa cola explica por qué los equipos concatenaban archivos, dibujaban sprites y repartían los recursos entre varios nombres de host.

Mejoras

El multiplexado permite que una página pida decenas de archivos sin esperar una conexión libre.
HPACK comprime las cabeceras repetidas, de modo que las cookies y el user agent no se envían enteros en cada petición.
El antiguo árbol de prioridades de flujos está obsoleto. La RFC 9218 lo sustituye por una cabecera Priority (urgencia de 0 a 7 y un indicador incremental).
La RFC 9113 indica que el bloqueo de cabeza de línea a nivel de TCP no se trata. Un paquete perdido sigue deteniendo todos los flujos de la conexión.
HTTP/3 mantiene la semántica y cambia el transporte

HTTP/3 (RFC 9114, junio de 2022) conserva el modelo HTTP, pero circula sobre QUIC en lugar de TCP. Un paquete perdido solo detiene el flujo al que pertenece, mientras que con HTTP/2 detiene todas las transferencias de la conexión.

Mejoras

La compresión de cabeceras pasa de HPACK a QPACK, pensado para flujos que pueden llegar en desorden.
El beneficio depende de la pérdida de paquetes. No lo hemos medido aquí, así que no prometemos ninguna ganancia de velocidad.
La adopción es real, pero difícil de medir. El Web Almanac 2024 contó un 7 % de las páginas de inicio en escritorio y un 9 % en móvil cargadas por HTTP/3 en su rastreo. Su autor estima que el soporte real se acerca al 30 %.
En el mismo capítulo, el 71 % de las páginas de inicio en escritorio y el 70 % en móvil se servían por HTTP/2. El 85 % de las peticiones usaban HTTP/2 o HTTP/3.
Lo que no cambia ninguno de los dos

Los dos protocolos mueven bytes. Ninguno cambia cuántos bytes tiene un archivo y ninguno analiza tu código.

Mejoras

El Content-Encoding (gzip o brotli) funciona igual en HTTP/1.1, HTTP/2 y HTTP/3.
Tras la descompresión, el navegador tiene el texto completo del script. Debe analizarlo y compilarlo entero, sea cual sea el protocolo que lo entregó.
El push del servidor, pensado para enviar archivos antes de que se pidan, está desactivado por defecto desde Chrome 106. El equipo de Chrome cita resultados débiles (cerca del 1,25 % de los sitios HTTP/2 lo usaban) y recomienda 103 Early Hints.
103 Early Hints solo envía indicios y deja la decisión al navegador. El Web Almanac 2024 lo encontró en el 2,9 % de las páginas de inicio en escritorio.
Lo que la minificación sigue ahorrando tras la compresión

Usamos el banco de pruebas de minificación de FastMinify (edición 2026-10). Mide archivos sin minificar de bibliotecas públicas en bruto, con gzip nivel 9 y con brotli calidad 11. Cada cifra es una suma sobre los archivos de un lenguaje. JavaScript usa Terser 5.51.2 con su configuración por defecto, CSS usa CSSO y JSON usa JSON.stringify.

Mejoras

JavaScript, 10 archivos: 5 637 983 bytes en bruto y 1 142 675 con gzip. Minificados, 1 809 323 bytes en bruto y 566 618 con gzip, es decir, un 67,9 % y un 50,4 % menos.
El mismo JavaScript con brotli: 899 755 bytes antes y 484 012 después (un 46,2 % menos).
CSS, 6 archivos: 1 593 647 bytes en bruto y 1 338 588 minificados (un 16,0 % menos). Con gzip, 161 522 frente a 151 049 (un 6,5 % menos). Con brotli, 106 426 frente a 99 630 (un 6,4 % menos).
JSON, 6 archivos con sangría: 14 199 411 bytes en bruto y 7 747 070 minificados (un 45,4 % menos). La ganancia es del 28,8 % con gzip y del 15,8 % con brotli.
Lee estas cifras como un techo. El corpus es código fuente sin minificar, con comentarios y sangrías, y tus archivos darán menos si ya son austeros.
644 módulos o un solo archivo

Descargamos lodash-es 4.18.1, que entrega 644 módulos JavaScript, minificamos cada módulo con esbuild y comprimimos con gzip nivel 9 y brotli calidad 11. Es un caso extremo, porque pocas páginas cargan 644 módulos, pero muestra el mecanismo.

Mejoras

644 módulos minificados pesan 189 745 bytes. Comprimidos uno a uno suman 119 525 bytes con gzip y 99 805 con brotli.
Los mismos módulos minificados unidos en un solo archivo se comprimen a 50 361 bytes con gzip (un 58 % menos) y 41 504 con brotli.
Agrupada y minificada por esbuild, con los imports resueltos, la biblioteca pesa 97 292 bytes, que son 35 489 con gzip y 31 205 con brotli.
El módulo mediano pesa 157 bytes minificado y 143 bytes tras gzip. Un archivo tan pequeño apenas tiene repeticiones internas y la compresión casi no encuentra nada.
Estas sumas ignoran las 644 peticiones y el tiempo que tarda el navegador en descubrir los imports nivel por nivel.
El tiempo de compilación en V8

Compilamos cinco bibliotecas con V8 (Node 26.4.0 en un Apple M4 Max), una vez tal como se entregan y otra minificadas con Terser. La prueba usa new vm.Script con una fuente que cambia en cada pasada, para evitar la caché de compilación. Cada cifra es la mediana de 30 pasadas y después la mediana de cinco series.

Mejoras

lodash: 533 KiB entregados y 70 KiB minificados. Compilación en 1,9 ms frente a 1,2 ms.
moment.js: 179 KiB y 61 KiB. 1,1 ms frente a 0,8 ms.
jQuery 4.0.0: 250 KiB y 77 KiB. 1,3 ms frente a 1,2 ms.
d3: 573 KiB y 272 KiB. 5,7 ms frente a 4,9 ms.
react-dom, build de desarrollo: 1 155 KiB y 378 KiB. 6,0 ms frente a 4,8 ms.
Es solo la compilación de primer nivel, en una máquina rápida. Los teléfonos son más lentos y no probamos ninguno. El equipo de V8 escribió en 2019 que V8 analiza, en la mayoría de las conexiones, más rápido de lo que el archivo se descarga. El tamaño transferido sigue siendo, pues, la palanca mayor.

Qué conservar y qué abandonar en 2026

Seguir haciendo

Estos pasos rinden con cualquier protocolo.

Minifica JavaScript, CSS, HTML y JSON antes de la compresión, con el minificador de JavaScript, el minificador de CSS, el minificador de HTML y el minificador de JSON.
Sirve brotli a los clientes que lo aceptan y gzip a los demás, como se explica en la guía de GZIP y Brotli.
Agrupa en pocos archivos por ruta, separa el código de terceros del código propio y elimina el código que nadie llama (consulta tree shaking y minificación).
Pon un hash de contenido en cada nombre de archivo y cachea con un max-age largo y la directiva immutable.
Incrusta el CSS crítico en la página y carga el resto sin bloquear el renderizado, como en la guía del CSS crítico.
Envía 103 Early Hints o un enlace preload para los pocos archivos que necesita el primer renderizado.
Los hábitos de HTTP/1.1 que conviene dejar

Cada uno tenía sentido con seis conexiones por host. Algunos ahora te cuestan algo.

Repartir los recursos entre varios nombres de host (sharding de dominios).
Contar con el push del servidor.
Dibujar un sprite solo para reducir el número de peticiones. Las peticiones son baratas hoy, y un icono modificado invalida toda la hoja.
Concatenar todos los scripts del sitio en un solo archivo.
Incrustar archivos como data URI en Base64 para evitar una petición.

Comprobar lo que tu servidor envía de verdad

Qué protocolo sirvió la página

Dos comprobaciones rápidas dan la respuesta, y una tercera explica por qué una primera visita suele mostrar h2.

En las DevTools de Chrome, abre el panel Network, haz clic derecho en la cabecera de las columnas y activa Protocol. La columna muestra http/1.1, h2 o h3 para cada petición.
Con curl, pide las cabeceras de un archivo y lee la primera línea. HTTP/2 200 indica que la conexión usó HTTP/2.
Un servidor anuncia HTTP/3 con una cabecera alt-svc. El navegador prueba entonces HTTP/3 en una conexión posterior, por eso la primera petición de una visita suele pasar por h2.
El 22 de octubre de 2026, fastminify.com respondió a una petición curl por HTTP/2 y anunció HTTP/3 en su cabecera alt-svc. Nuestro curl no admite HTTP/3, así que solo pudimos leer el anuncio.
Si la respuesta está comprimida y cómo

La codificación depende de la cabecera que envía el cliente, así que prueba con la de un navegador.

Pide el archivo una vez por cada codificación que te interese, luego con la cabecera completa de un navegador, y lee content-encoding cada vez.
Un servidor puede responder gzip aunque el cliente ofrezca gzip y br. Compara lo que vuelve para br solo y para la cabecera completa.
Comprueba que vary: Accept-Encoding está presente, para que una caché no entregue un cuerpo brotli a un cliente que no puede leerlo.
Compara los bytes transferidos con el tamaño descodificado. La sección de código de más abajo trae los comandos curl.

Cinco errores que sobreviven al paso a HTTP/2

Abandonar la minificación porque el protocolo es moderno

Pasar a HTTP/2 o HTTP/3 no es motivo para servir código legible. El protocolo no decide qué hay dentro del archivo.

Quitar el paso de minificación del build después de que el CDN pasara a HTTP/2.
Enviar comentarios, sangrías y nombres largos a producción porque la compresión se encargará.
Probar solo en una conexión de oficina rápida, donde los bytes de más pasan inadvertidos.
Sin minificación, el tamaño gzip de nuestros 10 archivos JavaScript se duplica, de 566 618 a 1 142 675 bytes.
Conserva el paso de minificación y mide su efecto después de la compresión, no antes.
Servir cientos de módulos en producción

Los módulos nativos y HTTP/2 permiten servir los archivos fuente tal cual. El equipo de V8 sigue recomendando agrupar para producción, y entregar sin agrupar solo aplicaciones pequeñas de menos de unos 100 módulos.

Entregar a producción un árbol de dependencias sin agrupar.
Contar las peticiones en el panel Network y dar todo por bueno porque están multiplexadas.
Olvidar que los imports se descubren nivel por nivel, de modo que un árbol profundo añade viajes de ida y vuelta.
En nuestra prueba con lodash-es, comprimir módulo a módulo dio 119 525 bytes donde un solo archivo dio 50 361.
Agrupa por ruta o por funcionalidad en un puñado de archivos y añade una indicación modulepreload para los chunks críticos.
Agrupar todo el sitio en un solo archivo

El exceso contrario es igual de habitual. Un solo bundle para todas las páginas significa que cada despliegue invalida toda la caché y que cada página descarga código que nunca ejecuta.

Un único main.js para todas las rutas.
Ningún hash de contenido en los nombres de archivo, así que no hay caché larga posible.
El código de terceros mezclado con el propio, de modo que un arreglo de una línea vuelve a descargar un framework.
La guía de módulos de v8.dev señala que los archivos sin agrupar pueden cargar más rápido en visitas posteriores, con la caché caliente.
Separa el código de terceros del propio, nombra los archivos por hash de contenido y sírvelos con un max-age largo e immutable.
Mantener los apaños de HTTP/1.1

Varios hábitos solo tenían sentido con seis conexiones por host. Nuestra guía de Base64 detalla el sobrecoste de incrustar archivos de esta forma.

Repartir los recursos entre los hosts cdn1, cdn2 y cdn3. Eso renuncia a la conexión única en la que se apoya el multiplexado y añade trabajo de DNS y de establecimiento de la conexión.
Contar con el push del servidor de HTTP/2, que Chrome no admite por defecto desde la versión 106.
Incrustar imágenes como data URI en Base64, lo que las hace un 33 % más grandes y las deja sin caché propia, separada de la página.
Sirve los recursos desde un solo host, usa 103 Early Hints o un enlace preload para los archivos críticos y deja las imágenes como archivos.
Esperar que HTTP/3 arregle una página pesada

HTTP/3 mejora cómo se recupera una conexión tras perder paquetes. No reduce el tamaño de la página.

Activar HTTP/3 en el CDN y dejar de lado el trabajo de rendimiento.
Esperar un Largest Contentful Paint más corto cuando la causa es un script de 1 MB.
Comprobar solo que la columna del protocolo dice h3.
Considera HTTP/3 una mejora gratuita para redes poco fiables y mantén tu presupuesto de bytes.

Cuatro afirmaciones sobre HTTP/2, HTTP/3 y el tamaño de los archivos

HTTP/2 hace inútil la minificación

La afirmación trata un transporte más rápido como si redujera la carga útil.

Falso. En nuestros 10 archivos JavaScript, la minificación quitó el 50,4 % de los bytes gzip y el 46,2 % de los bytes brotli. HTTP/2 no cambia ninguno de esos bytes.
Gzip y brotli ya hacen el trabajo de la minificación

Compresión y minificación se solapan, pero actúan sobre cosas distintas. La compresión elimina la repetición. La minificación elimina lo que el programa nunca necesitó.

En parte cierto para CSS, no para JavaScript. Solo con gzip, nuestro JavaScript queda en el 20 % de su tamaño, y la minificación divide por dos lo que queda. En CSS, el segundo paso vale un 6,5 %.
Con HTTP/2 nunca hay que agrupar

El multiplexado levantó el límite de peticiones en paralelo, no los demás costes de un archivo.

Mayormente falso. El equipo de V8 sigue recomendando agrupar para producción, y nuestra prueba de 644 módulos paga 2,4 veces más bytes gzip que el mismo código en un archivo. Por debajo de unos 100 módulos, entregar sin agrupar es aceptable.
HTTP/3 hará rápida una página lenta

HTTP/3 resuelve un problema de red, la pérdida de paquetes en una conexión compartida.

No cambia ni el número de bytes ni el tiempo de compilación. Ayuda sobre todo donde se pierden paquetes. Mide en tus propias páginas antes de esperar una mejora.

Minificar y medir con FastMinify

Minificar y comparar

Estos minificadores funcionan en tu navegador y muestran el tamaño original y el de salida: minificador de JavaScript, minificador de CSS, minificador de JSON y minificador de HTML.

1

Pega o suelta el archivo

Pega el código en el panel de entrada o suelta un archivo. En JavaScript, elige el nivel de compresión (conservador, normal o agresivo).

2

Lee el panel Compresión

El panel muestra el tamaño original, el tamaño de salida y el porcentaje ahorrado. Son tamaños sin comprimir, así que compáralos con las cifras en bruto de este artículo, no con lo que viaja.

3

Revisa la opción de console

El minificador de JavaScript quita por defecto las llamadas a console y las instrucciones debugger (opciones «Eliminar console» y «Eliminar debugger»). Desactívalas si tu código depende de ellas.

Unir varios archivos antes de minificar

Las páginas de los minificadores de JavaScript, CSS, HTML, XML, SVG y SQL tienen un botón «Concatenar archivos». Une los archivos que elijas y minifica el resultado.

1

Abre Concatenar archivos

Selecciona «Concatenar archivos» en la página del minificador y añade tus archivos. Arrástralos al orden en que deben ejecutarse.

2

Concatena y minifica

Ejecuta «Concatenar y minificar». En JavaScript, la herramienta une los archivos con un punto y coma en su propia línea, para que un archivo no se trague al siguiente, y luego minifica el conjunto. No resuelve imports: para un grafo de dependencias real, usa tu bundler (consulta minificadores en línea y herramientas de build).

Reproducir las mediciones con tus propios archivos

Comprobar protocolo y codificación con curl

curl -I envía una petición HEAD, y algunos servidores responden a ella distinto que a un GET. Sustituye la URL por la de uno de tus archivos.

Ejemplo básico

# La primera línea indica HTTP/2 o HTTP/3 curl -sI https://example.com/app.js | head -n 1 # ¿Se anuncia HTTP/3? Busca una cabecera alt-svc curl -sI https://example.com/app.js | grep -i alt-svc # Codificación elegida por el servidor: br solo y luego la cabecera de un navegador curl -sI -H 'Accept-Encoding: br' https://example.com/app.js | grep -i content-encoding curl -sI -H 'Accept-Encoding: gzip, deflate, br, zstd' https://example.com/app.js | grep -i content-encoding # Bytes transferidos y luego bytes descodificados curl -s -H 'Accept-Encoding: gzip' -o /dev/null -w '%{size_download}\n' https://example.com/app.js curl -s --compressed https://example.com/app.js | wc -c
Medir los tamaños en bruto, gzip y brotli con Node

Guarda el script como size.mjs. Usa gzip nivel 9 y brotli calidad 11, la configuración del banco de pruebas.

Ejemplo básico

import { readFileSync } from 'node:fs' import { gzipSync, brotliCompressSync, constants } from 'node:zlib' const file = process.argv[2] const buf = readFileSync(file) const gzip = gzipSync(buf, { level: 9 }).length const brotli = brotliCompressSync(buf, { params: { [constants.BROTLI_PARAM_QUALITY]: 11, [constants.BROTLI_PARAM_SIZE_HINT]: buf.length, }, }).length console.log(`${file}: raw ${buf.length}, gzip ${gzip}, brotli ${brotli}`)

Uso

node size.mjs dist/app.js node size.mjs dist/app.min.js
Comparar muchos archivos con uno solo

Esto mide solo la compresión. Unir módulos ES de este modo no produce un script que funcione, así que úsalo sobre una carpeta para ver el coste de los archivos minúsculos.

Ejemplo básico

import { readdirSync, readFileSync } from 'node:fs' import { join } from 'node:path' import { gzipSync } from 'node:zlib' const dir = process.argv[2] const files = readdirSync(dir) .filter((name) => name.endsWith('.js')) .map((name) => readFileSync(join(dir, name))) const oneByOne = files.reduce((sum, buf) => sum + gzipSync(buf, { level: 9 }).length, 0) const asOneFile = gzipSync(Buffer.concat(files), { level: 9 }).length console.log(files.length, 'files', { oneByOne, asOneFile })
Medir el tiempo de compilación en V8

El script compila un script clásico sin ejecutarlo. new Script no acepta módulos ES con import o export.

Ejemplo básico

import { readFileSync } from 'node:fs' import { Script } from 'node:vm' const source = readFileSync(process.argv[2], 'utf8') const times = [] for (let i = 0; i < 33; i++) { // un comentario final único evita la caché de compilación const start = performance.now() new Script(`${source}\n//run${i}`) times.push(performance.now() - start) } times.splice(0, 3) times.sort((a, b) => a - b) console.log(`median ${times[Math.floor(times.length / 2)].toFixed(2)} ms`)

Sigue minificando y abandona los hábitos de HTTP/1.1

HTTP/2 y HTTP/3 hicieron baratas las peticiones pequeñas. No hicieron pequeños los archivos grandes. La minificación sigue reduciendo a la mitad el tamaño comprimido de un JavaScript sin minificar, quita unos puntos al CSS y reduce el trabajo de compilación. Lo que perdió valor es la caja de herramientas de HTTP/1.1, hecha de nombres de host multiplicados, push y bundles gigantes. Minifica, comprime con brotli, agrupa con medida y juzga el resultado por los bytes que viajan.

Sigue minificando JavaScript, CSS, HTML y JSON antes de la compresión.
Sirve brotli con gzip como alternativa y comprueba qué elige tu servidor para la cabecera de un navegador.
Agrupa en un puñado de archivos en caché por ruta, ni un solo archivo ni cientos.
Abandona el sharding de dominios y el push del servidor, y usa 103 Early Hints o preload para los archivos críticos.
Lee las ganancias tras la compresión y en la red, y prueba en un teléfono lento antes de anunciar una mejora de velocidad.
Compartir este artículo
Compartir este artículo: