Сжатие — gzip и brotli
gzip и brotli — алгоритмы сжатия текстовых HTTP-ресурсов (HTML, CSS, JS, JSON), которые уменьшают их объём в 2-5 раз при передаче по сети. Brotli даёт на 15-25% лучшее сжатие по сравнению с gzip.
Зачем нужно
Сжатие — самая простая оптимизация с максимальным эффектом: 100KB JavaScript → 30KB с gzip → 26KB с brotli. Для медленных соединений (3G, мобайл) разница в несколько мегабайт — разница между пользователем, который дождался страницы, и тем, кто ушёл.
Где используется
- Все текстовые ресурсы: HTML, CSS, JS, JSON, XML, SVG, font woff
- REST API и GraphQL-ответы
- Server-Sent Events и WebSocket фреймы (частично)
Основной контент
Сравнение алгоритмов
gzip: Поддерживается везде, быстрое сжатие/распаковка
brotli: Лучшее сжатие (+15-25% vs gzip), браузеры с 2015, Nginx с 1.11.5
Поддержка браузерами (2026): brotli — 96%+
Правило: используй brotli с gzip fallback
Nginx: gzip + brotli
# nginx.conf
http {
# gzip (fallback для старых клиентов)
gzip on;
gzip_comp_level 5;
gzip_min_length 256;
gzip_proxied any;
gzip_vary on;
gzip_types
text/plain text/css application/json
application/javascript text/xml application/xml
application/xml+rss text/javascript image/svg+xml;
# brotli (требует модуль ngx_brotli)
brotli on;
brotli_comp_level 6;
brotli_min_length 256;
brotli_types
text/plain text/css application/json
application/javascript text/xml application/xml
image/svg+xml;
}
Express + Compression middleware
const express = require('express');
const compression = require('compression');
const shrinkRay = require('shrink-ray-current'); // gzip + brotli
const app = express;
// Опция 1: только gzip (простое решение)
app.use(compression({
level: 6, // Уровень сжатия 1-9 (6 - баланс скорость/размер)
threshold: 1024, // Не сжимать ответы < 1KB
}));
// Опция 2: brotli + gzip (лучше)
app.use(shrinkRay);
Статическое сжатие (pre-compression)
# Сжать файлы при сборке, отдавать готовые .gz и .br
# Vite/webpack делают это через плагины
# vite.config.js
import viteCompression from 'vite-plugin-compression';
export default {
plugins: [
viteCompression({ algorithm: 'gzip' }),
viteCompression({ algorithm: 'brotliCompress', ext: '.br' }),
],
};
# Nginx: отдавать pre-compressed файлы
location ~* \.(js|css|html|svg)$ {
gzip_static on; # Ищет file.js.gz
brotli_static on; # Ищет file.js.br
}
Проверка сжатия
# Проверить наличие Content-Encoding в ответе
curl -I -H "Accept-Encoding: br, gzip" https://example.com/bundle.js \
| grep -i 'content-encoding\|content-length'
# Ожидаемый ответ:
# content-encoding: br
# content-length: 26458 # Сжатый размер
# Без сжатия:
# content-length: 98000 # ~4x больше
Что НЕ сжимать
# Уже сжатые форматы — не трогать!
# JPEG, PNG, WEBP, AVIF, GIF → уже сжаты
# WOFF2 → уже сжат (brotli внутри формата)
# MP4, MP3, ZIP, PDF → уже сжаты
# Сжатие этих форматов только добавляет CPU overhead без выгоды
Частые ошибки
- Не включён
gzip_vary onв Nginx — CDN кеширует один вариант для всех - Сжатие очень маленьких ответов (<256 bytes) — overhead заголовков превышает выгоду
- Не добавлен
Accept-EncodingвVary— браузер/CDN не различает сжатый и несжатый - Высокий уровень сжатия (9) в real-time — CPU bottleneck при высоком трафике