
Gzip и кеширование в Nginx: ускоряем отдачу без лишнего риска
Включаем gzip в Nginx для текстовых ресурсов, проверяем Vary и Content-Encoding, не сжимаем изображения и отделяем compression от Cache-Control.
Содержание
Текстовый CSS-файл хорошо сжимается, а WebP-изображение уже хранит данные в сжатом виде. Если без разбора пропустить оба ответа через gzip, сервер потратит процессор на изображение почти без уменьшения трафика.
Настроим сжатие только для понятных текстовых MIME-типов и проверим его по заголовку Content-Encoding. Затем отдельно разберём кеш: gzip уменьшает один ответ, а Cache-Control определяет, понадобится ли передавать этот ответ снова.
Включите gzip для текстовых ответов
Следующий блок располагается в контексте http. Он включает gzip для ответов от 1024 байт, добавляет заголовок Vary и перечисляет дополнительные текстовые типы:
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_comp_level 5;
gzip_types
text/css
text/plain
application/javascript
application/json
application/xml
image/svg+xml;
Это отправная точка, а не универсальный максимум. Ответы text/html Nginx сжимает при включённом gzip и без добавления в gzip_types. Конкретные MIME-типы проверьте по заголовку Content-Type вашего сайта.
Высокий gzip_comp_level сильнее загружает CPU и не гарантирует заметной дополнительной экономии. Измерьте несколько характерных файлов на реальном сервере. Для маленьких ответов заголовки и работа компрессора могут стоить больше полученной выгоды, поэтому используется gzip_min_length.
Какие типы не добавлять
JPEG, WebP, AVIF, MP4, gzip и zip уже используют компрессию. Повторный gzip обычно почти не уменьшает их. Не используйте gzip_types * без измерений: он скрывает выбор и может обрабатывать неподходящие ответы.
SVG и JSON текстовые, но иногда содержат чувствительные данные. Сжатие динамических секретов рядом с отражаемым пользовательским вводом может создавать побочные каналы. Для авторизованных и персональных ответов оцените модель угроз и не включайте компрессию глобально только ради процента в тесте скорости.
Vary и промежуточные кеши
Клиент сообщает поддержку в Accept-Encoding. Один URL может иметь сжатый и несжатый вариант. Параметр ниже просит Nginx добавить соответствующее различие в заголовки ответа:
gzip_vary on;
добавляет Vary: Accept-Encoding, чтобы proxy и CDN не отдали gzip клиенту, который его не принимает. Проверьте, не переписывает ли этот заголовок внешний CDN.
Для ответов от proxied-приложения поведение gzip_proxied зависит от заголовка Via и параметров кеширования. Не включайте any автоматически: сначала решите, какие приватные или авторизованные ответы допустимо сжимать.
Сравните ответы одного ресурса
Сначала проверьте и перечитайте конфигурацию. Затем дважды запросите заголовки CSS-файла: во втором запросе клиент явно сообщает поддержку gzip:
sudo nginx -t
sudo systemctl reload nginx
curl -sS -D - -o /dev/null https://example.com/app.css
curl -sS -H 'Accept-Encoding: gzip' -D - -o /dev/null https://example.com/app.css
Во втором ответе ожидается Content-Encoding: gzip, если размер и тип подходят. Проверьте Vary, Content-Type, Cache-Control и Content-Length. Для оценки объёма сохраните тело двух вариантов во временный каталог и сравните размеры, не загрязняя проект.
Если сжатия нет, проверьте тип, длину, область действия конфигурации и уже выставленный Content-Encoding upstream. Не добавляйте CSS как application/octet-stream только ради gzip — сначала исправьте MIME.
Предварительно сжатые файлы
Модуль gzip_static может отдавать заранее созданный файл .gz, если он существует рядом с оригиналом. Следующая команда покажет, собран ли Nginx с этим модулем:
nginx -V 2>&1 | grep http_gzip_static_module
Предварительное сжатие снижает CPU на запрос, но усложняет build: оригинал и .gz должны обновляться вместе, а даты — быть согласованы. Для небольшого сайта динамического gzip часто достаточно. Не включайте gzip_static always, пока не понимаете поведение клиентов без gzip.
Сжатие и кеш — разные задачи
Gzip уменьшает один ответ. Cache-Control позволяет не передавать его снова. Если имя файла содержит хеш содержимого и меняется при каждой сборке, для таких ресурсов можно задать длительное immutable-кеширование:
location ~* \.(?:css|js|woff2|webp|avif)$ {
expires 1y;
add_header Cache-Control "public, max-age=31536000, immutable";
}
Такой срок безопасен только если URL меняется при изменении содержимого. Для index.html долгий immutable-кеш приведёт к устаревшей странице. Подробная схема есть в статье про кеширование статики.
Контроль результата и откат
После включения сравните трафик, CPU Nginx и время ответа под обычной нагрузкой. Проверьте HTML, CSS, JS, JSON и хотя бы одно изображение, которое не должно получить gzip. Если растёт CPU или ломается промежуточный кеш, верните сохранённый блок, выполните nginx -t и reload.
Сначала разберитесь со структурой конфигурации Nginx, чтобы директивы не дублировались в разных include.
Чек-лист перед завершением
Проверьте страницу с авторизацией отдельно от публичной, а статический файл — через origin и через CDN. Убедитесь, что proxy не удаляет Vary, не выполняет повторную компрессию и не сохраняет приватный ответ в общем кеше. Для версионированных assets сравните два последовательных запроса: второй должен использовать ожидаемую cache-политику.
Не оценивайте результат только по проценту сжатия. Важны переданные байты на реальном трафике, загрузка CPU, время до первого байта и отсутствие ошибок декодирования. Если сайт уже отдаёт Brotli на внешнем CDN, gzip на origin может оставаться fallback, но их зоны ответственности нужно документировать.
После каждого изменения frontend-сборки проверяйте корректный Content-Type: компрессор и кеш не должны маскировать неверную MIME-настройку. Для HTML оставляйте стратегию обновления, при которой пользователь не получает старую оболочку с уже удалёнными asset-файлами.
Первоисточники
- Nginx: ngx_http_gzip_module — gzip, типы, минимальная длина и Vary.
- Nginx: ngx_http_gzip_static_module — выдача предварительно сжатых файлов.
Самопроверка
Проверьте, что материал усвоен
Ответьте на все вопросы. Результат сохранится только в этом браузере и будет учтён в статистике прочитанных материалов.
Разбираем коротко
Частые вопросы
Нужно ли добавлять text/html в gzip_types?
Нет необходимости: документация Nginx указывает, что ответы text/html сжимаются всегда при включённом gzip. В gzip_types перечисляют дополнительные текстовые MIME-типы.
Стоит ли сжимать WebP, JPEG, ZIP и видео через gzip?
Обычно нет: эти форматы уже сжаты, а повторная обработка тратит CPU при минимальной экономии или увеличении размера. Сосредоточьтесь на HTML, CSS, JavaScript, JSON, XML и текстовых файлах.
Заменяет ли gzip настройку Cache-Control?
Нет. Gzip уменьшает передаваемый ответ, а кеширование определяет, нужно ли запрашивать его снова. Для версионированных статических файлов и HTML применяются разные cache-политики.


