El texto que descargas de una web viaja comprimido al 20-30% de su tamaño original. Esa compresión invisible —negociada entre navegador y servidor en una cabecera— es una de las optimizaciones de mayor impacto por esfuerzo invertido, y aun así muchos proyectos la tienen mal configurada o desactivada. Aquí va el mecanismo completo y su puesta a punto.
La negociación en dos cabeceras
Todo el protocolo cabe en cuatro líneas:
# El navegador anuncia lo que soporta, con prioridad:
Accept-Encoding: gzip, deflate, br, zstd
# El servidor responde con lo elegido:
Content-Encoding: br
Si el servidor no responde con Content-Encoding, el recurso viaja sin comprimir — eso es exactamente lo que auditar cuando sospechas que algo no va. Los navegadores modernos soportan los cuatro: gzip (universal), deflate (zlib, raro hoy), br (Brotli) y zstd (Zstandard, el recién llegado).
El motor compartido: LZ77 + Huffman
Gzip y Brotli comparten dos ideas fundamentales, heredadas de DEFLATE:
LZ77 (sustitución de repeticiones): cuando aparece una secuencia ya vista antes, se emite una referencia atrás —"copia 25 bytes desde hace 340 posiciones"— en lugar de repetirla. En HTML/CSS/JS las repeticiones son constantes: etiquetas, nombres de clase, keywords, selectores.
Huffman (códigos de longitud variable): los símbolos frecuentes reciben códigos cortos y los raros, largos. La letra "e" puede costar 4 bits; un carácter raro 15.
La diferencia entre formatos está en cuánto optimizan cada pieza:
| Gzip | Brotli | |
|---|---|---|
| Ventana de LZ77 | 32 KB | hasta 16 MB |
| Códigos Huffman | dinámicos por bloque | contextos múltiples |
| Diccionario predefinido | No | Sí (120 KB web común) |
| Ratio típico vs gzip | referencia | 15-25% menor |
La ventana grande de Brotli es clave para ficheros grandes: una repetición a 500 KB de distancia es invisible para gzip pero capturada por brotli. Y el diccionario integrado —fragmentos frecuentes de HTML, CSS, JS y palabras comunes inglesas— significa que incluso un fichero pequeño de 2 KB se comprime como si ya llevara medio archivo visto previamente.
Zstd añade otra dimensión: ratio cercano a brotli con velocidad de compresión mucho mayor, ideal donde CPU importa (CDNs re-comprimiendo al vuelo). Su adopción web crece rápido.
Niveles de compresión: el trade-off real
Ambos formatos ofrecen niveles (gzip 1-9, brotli 0-11). Más nivel = más CPU gastada buscando mejores codificaciones = fichero menor. La curva es dura:
- Gzip nivel 6 → 1: el fichero crece solo ~5% y comprime 10× más rápido.
- Brotli nivel 11 vs 5: ahorra ~3-6% adicional y puede tardar 10-50× más.
La estrategia profesional: compresión estática — comprime en build time (brotli -11 para todo) y sirve los ficheros .br preparados. Así el nivel máximo no cuesta nada en runtime. La compresión dinámica (al vuelo por petición) queda para contenido generado en vivo, con niveles medios.
Qué comprimir y qué no
Compresión alta: HTML, CSS, JS, SVG, JSON, XML, texto — ratios típicos 70-85%. Un bundle JS de 900 KB baja a ~250 KB gzipped / ~200 KB brotli.
No comprimir (ya comprimidos internamente): JPG, PNG, WebP, AVIF, MP4, WebM, PDF, WOFF2. Comprimirlos de nuevo gasta CPU para ganar <1% e incluso puede empeorar. Nota importante: WOFF2 ya viene comprimido con brotli internamente — por eso pesa tan poco.
Y una interacción crítica: la compresión no sustituye a la minificación, la complementa. Minificar elimina bytes (espacios, comentarios, nombres largos); la compresión codifica mejor los restantes. Un minificado comprime además mejor porque concentra símbolos repetidos. Pipeline correcto: minificar → comprimir. Nuestro minificador de código cubre el primer paso localmente.
Configuración práctica
Nginx (gzip nativo; brotli requiere módulo ngx_brotli):
gzip on;
gzip_types text/plain text/css application/json application/javascript image/svg+xml;
gzip_min_length 1024;
gzip_comp_level 6;
# Con ngx_brotli:
brotli on;
brotli_comp_level 5;
brotli_types text/plain text/css application/json application/javascript image/svg+xml;
Si sirves desde Vercel/Netlify/Cloudflare, esto ya viene hecho y bien afinado — una razón más para el edge moderno. En servidores propios, verifica tras configurar:
curl -sI -H "Accept-Encoding: br,gzip" https://midominio.es/ | grep -i content-encoding
Si no devuelve content-encoding, algo está desactivado o el tipo MIME no está listado — error clásico: servir .svg sin declarar image/svg+xml en gzip_types.
Preguntas frecuentes
¿Comprimir respuestas dinámicas? Sí para JSON/texto de API, con nivel medio y cuidado con latencia generada. Para HTML renderizado, evalúa: si tu TTFB ya es justo, comprimir al vuelo puede estorbar más que ayudar — caché primero.
¿Brotli funciona sobre HTTPS únicamente? Los navegadores solo anuncian br en conexiones seguras. Sobre HTTP plano, gzip. En 2026 toda web seria va sobre HTTPS de todos modos.
¿Cuánto mejora zstd frente a brotli? Ratios similares (±3%); zstd gana claramente en velocidad de compresión. Para estáticos precomprimidos la diferencia es irrelevante; para compresión al vuelo masiva, zstd tiene futuro.
Minifica tu HTML, CSS y JS antes de comprimir con nuestro minificador online, gratis y directamente en tu navegador.