Включить Gzip на сервере можно за несколько минут.
Настроить сжатие так, чтобы оно действительно уменьшало сетевой трафик, корректно работало через CDN и reverse proxy, не создавало проблем с кэшем и не тратило лишний CPU - уже инженерная задача.
Именно в таких деталях обычно проявляется разница между сайтом, который просто "работает", и технически нормально спроектированным веб-проектом.
В ApLike мы не ограничиваемся настройкой:
gzip on;Смотрим на весь путь ответа:
Приложение → Web-сервер → Reverse Proxy → CDN → Браузер
и проверяем, какое содержимое фактически получает конечный пользователь.
Используем Brotli, а не ограничиваемся Gzip
Gzip остаётся надёжным и широко поддерживаемым алгоритмом.
Но современный web stack позволяет использовать Brotli (br), который для текстовых ресурсов обычно обеспечивает более эффективное сжатие.
Поэтому нормальная схема выглядит не так:
Gzip включён → задача закрытаа так:
Поддерживается Brotli
↓
Content-Encoding: br
Brotli недоступен
↓
Content-Encoding: gzip
Сжатие не поддерживается
↓
Обычный ответТо есть используем лучший доступный алгоритм, сохраняя совместимость.
Не сжимаем всё подряд
Одна из характерных ошибок - включить компрессию для максимально большого количества MIME-типов.
Это выглядит как оптимизация, но может давать обратный эффект.
Хорошо сжимаются:
- HTML;
- CSS;
- JavaScript;
- JSON;
- XML;
- SVG;
- Другие текстовые форматы.
Но изображения, видео и архивы обычно уже используют собственное сжатие:
- WebP;
- AVIF;
- JPEG;
- PNG;
- MP4;
- WebM;
- ZIP.
Повторно компрессировать такие файлы почти бессмысленно.
CPU расходуется, а размер практически не меняется.
Мы настраиваем сжатие по принципу:
сжимать там, где уменьшается реальный объём передачи, а не там, где конфигурация выглядит длиннее.
Учитываем Vary: Accept-Encoding
Один URL может иметь несколько представлений:
app.js
├── Brotli
├── Gzip
└── без сжатияПоэтому одного Content-Encoding недостаточно.
При работе через браузерные кэши, CDN и reverse proxy необходимо корректно учитывать:
Vary: Accept-EncodingОн сообщает промежуточному кэшу, что ответ зависит от возможностей клиента.
Без корректного Vary инфраструктура может начать кэшировать неподходящую версию ресурса.
Например:
- Brotli-ответ попадёт клиенту без поддержки Brotli;
- Несжатая версия начнёт раздаваться всем пользователям;
- Разные уровни инфраструктуры будут хранить несовместимые варианты ответа.
Такие ошибки редко заметны по внешнему виду сайта.
Но именно они отличают проверенную конфигурацию от настройки "по инструкции из интернета".
Разделяем статическое и динамическое сжатие
Сжатие требует вычислений.
Поэтому максимальный compression level не всегда означает максимальную скорость.
Для динамически генерируемой страницы слишком тяжёлое сжатие может увеличить нагрузку на CPU и ухудшить TTFB.
Получается простой trade-off:
Сильнее сжатие
↓
Меньше передаваемых данных
↓
Больше вычисленийПоэтому параметры выбираются с учётом:
- Размера ответа;
- Типа контента;
- Частоты запросов;
- Нагрузки;
- CPU;
- TTFB;
- Наличия CDN;
- Поведения кэша.
Для статики ситуация другая.
JavaScript, CSS и другие неизменяемые ресурсы можно предварительно сжимать:
app.js
app.js.gz
app.js.brТогда CPU не тратится на повторную компрессию каждого запроса.
Используем версионирование и долгий кэш
Сжатие нельзя рассматривать отдельно от HTTP-кэширования.
Для статических ресурсов хорошо работает схема с fingerprinting:
app.824bd1.js
styles.17af92.cssПосле изменения содержимого меняется и URL:
app.935ac7.jsЭто позволяет безопасно использовать долгий:
Cache-ControlПользователь не скачивает один и тот же JavaScript при каждом посещении, CDN не запрашивает его заново, а сервер не выполняет лишнюю работу.
В результате оптимизация строится сразу на нескольких уровнях:
Compression + Cache + Revisioning + CDN
а не одной настройкой web-сервера.
Проверяем конечный HTTP-ответ
Конфигурационный файл сам по себе ничего не доказывает.
Можно увидеть:
brotli onи всё равно получить у пользователя несжатый ответ.
Например, потому что:
- CDN изменяет заголовки;
- reverse proxy повторно обрабатывает ответ;
- MIME-type не включён;
- Правило действует не на тот location;
- Кэш содержит старую версию;
- upstream уже применил другую компрессию.
Поэтому проверяем то, что реально получает клиент.
Для Brotli:
curl -sI -H "Accept-Encoding: br" https://example.com/Ожидаем:
Content-Encoding: br
Vary: Accept-EncodingДля Gzip:
curl -sI -H "Accept-Encoding: gzip" https://example.com/Ожидаем:
Content-Encoding: gzipПроверяем в браузере
Дополнительно смотрим запросы через DevTools:
Network → Resource → Headers
Проверяем:
- content-encoding;
- vary;
- cache-control;
- Размер Transferred;
- Размер Resource.
Если сжатие действительно работает, переданный по сети объём должен быть меньше исходного размера подходящего ресурса.
Именно фактический HTTP-ответ является критерием результата.
Не галочка в панели хостинга.
Не установленный модуль.
Не строка в Nginx.
Типовые "оптимизации", которые ничего не оптимизируют
"Мы включили Gzip"
Но:
- Brotli не используется;
- JSON не сжимается;
- SVG не сжимается;
- CDN отдаёт другую версию;
- Vary отсутствует.
Формально компрессия включена.
Технически задача выполнена наполовину.
"Мы включили максимальное сжатие"
На динамических ответах CPU начинает тратить больше времени на compression.
В результате экономим несколько килобайт, одновременно увеличивая TTFB.
Оптимизация одной метрики ухудшает другую.
"Мы сжимаем вообще всё"
JPEG, WebP, AVIF и видео повторно отправляются на компрессию.
CPU расходуется без заметного уменьшения размера.
"У нас CDN, он всё сделает сам"
CDN действительно может выполнять часть работы.
Но нужно проверить:
- Какие алгоритмы используются;
- Что происходит между origin и CDN;
- Какие заголовки доходят до пользователя;
- Правильно ли разделяются cache variants;
- Используется ли Brotli;
- Как обрабатывается динамический HTML.
Сам факт наличия CDN не гарантирует корректную конфигурацию.
"PageSpeed показывает зелёный - значит всё хорошо"
Синтетическая проверка полезна, но не заменяет анализ инфраструктуры.
Нужно понимать:
- Реальный HTTP-response;
- Размер передачи;
- TTFB;
- cache hit/miss;
- Нагрузку;
- Работу CDN;
- Поведение origin.
Мы оптимизируем систему, а не оценку одного инструмента.
Почему мы уделяем внимание таким деталям
Brotli сам по себе не является уникальной технологией.
Его поддерживают современные web-серверы, CDN и браузеры.
Разница заключается не в том, знает ли разработчик слово Brotli.
Разница в том, насколько глубоко он понимает взаимодействие:
Browser
↓
HTTP
↓
Compression
↓
Cache
↓
CDN
↓
Reverse Proxy
↓
ApplicationВ производительности веб-проекта почти никогда нет одной волшебной настройки.
Небольшие технические решения складываются в общий результат:
- Меньше сетевого трафика;
- Меньше повторных запросов;
- Быстрее загрузка;
- Ниже нагрузка;
- Предсказуемое поведение CDN;
- Корректная работа кэша.
Не "включаем Brotli" - настраиваем передачу контента
Для нас техническая оптимизация не заканчивается установкой модуля или копированием готового конфига.
Мы проверяем:
какой ответ формирует приложение → что делает сервер → что происходит на proxy/CDN → что фактически получает браузер.
Поэтому при работе со сжатием учитываем одновременно:
- Brotli;
- Gzip fallback;
- MIME-типы;
- Content-Encoding;
- Accept-Encoding;
- Vary;
- CPU;
- TTFB;
- Cache-Control;
- Версионирование ресурсов;
- CDN;
- Фактические HTTP-ответы.
Именно такой уровень технических деталей позволяет не просто заявлять о производительности сайта, а понимать, почему он работает быстро и где искать причину, если перестанет.
Современный сайт состоит из таких деталей
HTTP-сжатие - только один небольшой элемент производительности.
Рядом находятся:
- HTTP-кэширование;
- CDN;
- Core Web Vitals;
- Оптимизация изображений;
- Серверный cache;
- frontend bundle;
- backend;
- База данных;
- network latency;
- Архитектура приложения.
По отдельности многие из этих настроек выглядят незначительными.
Но именно из них складывается техническое качество проекта.
Мы не используем технологии потому, что они звучат современно. Используем их там, где понимаем, какой эффект они дают, как взаимодействуют с остальной системой и как проверить результат.