Gzip и brotli в nginx: настройка сжатия Перейти к содержимому
+7 (920) 556-26-91 пн–пт: 10:00–19:00 (МСК)
Проконсультироваться Обсудить задачу

Инструкции

Сжатие в nginx: настройка gzip и brotli

Какие типы файлов сжимать, разбор директив gzip, установка и настройка brotli, проверка заголовков и кэширование статики.

Сжатие в nginx: настройка gzip и brotli

Короткий ответ: gzip в nginx включается тремя директивами — gzip on, gzip_types со списком типов и gzip_min_length, ниже которого сжимать невыгодно. Brotli даёт на тексте на 15–25 % меньше объёма, но его модуль не входит в стандартную сборку nginx и требует отдельной установки. Включать оба сразу можно: nginx отдаст brotli клиентам, которые его поддерживают, и gzip остальным.

Это часть работ по разработке и поддержке сайтов; смежная тема — установка и настройка nginx.

Зачем сжимать

HTML, CSS, JavaScript, JSON и SVG — текстовые форматы с высокой избыточностью. Сжатие уменьшает их в 3–10 раз. На медленном мобильном соединении это прямо влияет на время загрузки, а оно учитывается и в поисковых системах, и в конверсии.

Тип файла Сжимать Почему
HTML, CSS, JS, JSON, XML Да Текст, высокая избыточность
SVG Да Это XML внутри
JPEG, PNG, WebP, AVIF Нет Уже сжаты, эффекта не будет, только расход процессора
WOFF2 Нет Внутри уже применено сжатие
MP4, MP3 Нет Уже сжаты

Включение gzip для картинок — распространённая ошибка: трафик не уменьшается, а нагрузка на процессор растёт на каждом запросе.

Настройка gzip

Директивы размещаются в блоке http или в конкретном server:

gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 5;
gzip_min_length 1024;
gzip_types
    text/plain
    text/css
    text/xml
    text/javascript
    application/javascript
    application/json
    application/xml
    application/rss+xml
    image/svg+xml;

# отключить сжатие для старых версий IE
gzip_disable "msie6";
Директива Смысл
gzip_vary on Добавляет заголовок Vary: Accept-Encoding — без него кэши могут отдать сжатый ответ клиенту, который его не понимает
gzip_proxied any Сжимать и ответы для прокси и CDN; без этого сжатие может не применяться за Cloudflare
gzip_comp_level 5 Разумный компромисс: уровни 1–9 дают убывающую прибавку при растущем расходе процессора
gzip_min_length 1024 Файлы меньше килобайта сжимать невыгодно — заголовки съедят выигрыш

Уровень сжатия выше 6 почти не уменьшает размер, но заметно нагружает процессор. На сервере, который отдаёт много статики, разница между 5 и 9 ощутима по нагрузке и незаметна по трафику.

Brotli

Brotli даёт меньший размер, чем gzip, особенно на JavaScript и CSS. Модуль ngx_brotli не входит в стандартную сборку — его нужно устанавливать отдельно, а для этого часто пересобирать nginx. В репозиториях Debian и Ubuntu готового пакета обычно нет.

Если модуль подключён, настройка выглядит так:

brotli on;
brotli_comp_level 5;
brotli_static on;
brotli_types
    text/plain
    text/css
    text/xml
    text/javascript
    application/javascript
    application/json
    application/xml
    image/svg+xml;

Директива brotli_static on позволяет отдавать заранее подготовленные файлы .br, если они лежат рядом с оригиналом — тогда сжатие не тратит процессорное время вообще.

Проверка

Заголовок Content-Encoding в ответе показывает, применено ли сжатие:

# gzip
curl -s -H "Accept-Encoding: gzip" -I https://example.com/ | grep -i content-encoding

# brotli
curl -s -H "Accept-Encoding: br" -I https://example.com/ | grep -i content-encoding

# размер до и после
curl -s -o /dev/null -w "без сжатия: %{size_download} байтn" https://example.com/
curl -s -H "Accept-Encoding: gzip" -o /dev/null -w "gzip: %{size_download} байтn" https://example.com/

Если Content-Encoding не появляется, проверяйте в таком порядке: тип содержимого входит в gzip_types, размер больше gzip_min_length, ответ не отдаётся из кэша без заголовка Vary.

Кэширование статики

Сжатие работает вместе с кэшированием. Сжатый ответ выгодно кэшировать, чтобы не тратить процессор повторно:

location ~* .(css|js|svg|woff2)$ {
    expires 1y;
    add_header Cache-Control "public, immutable";
    access_log off;
}

location ~* .(jpg|jpeg|png|webp|avif|gif|ico)$ {
    expires 1y;
    add_header Cache-Control "public, immutable";
    access_log off;
}

Долгий срок хранения требует «отпечатка» в имени файла: при изменении содержимого меняется имя, и клиент забирает новую версию. Без этого посетители будут месяцами получать старый файл из кэша.

Что проверять после включения

  1. nginx -t — синтаксис конфигурации.
  2. systemctl reload nginx — применение без разрыва соединений.
  3. Проверка Content-Encoding для HTML, CSS и JS отдельно.
  4. Сравнение размера ответа до и после.
  5. Загрузка процессора после включения — на слабом сервере высокий уровень сжатия заметен.
  6. Проверка, что картинки и шрифты не попали в сжатие.

Отдельно стоит проверить сайт под нагрузкой: сжатие на каждый запрос — это работа процессора, и на сервере с одним ядром при большом трафике эффект может оказаться отрицательным. В таких случаях помогает gzip_static on с заранее подготовленными файлами.