Как включить сжатие Gzip и Brotli в Nginx
Практика3 минРедакция Innovialabs
Коротко
Gzip включается встроенными директивами gzip on и gzip_types, Brotli требует модуля ngx_brotli; сжимайте текстовые форматы на среднем уровне, статику сжимайте заранее, а результат проверяйте по заголовку Content-Encoding.
Как работает сжатие
Браузер в каждом запросе сообщает, какие алгоритмы понимает: Accept-Encoding: gzip, deflate, br. Сервер выбирает подходящий, сжимает ответ и помечает его заголовком Content-Encoding. Браузер распаковывает данные сам.
Сильнее всего выигрывают текстовые форматы: HTML, CSS, JavaScript, JSON, SVG. Обычно Brotli сжимает текст плотнее, чем gzip, а gzip поддерживается вообще всеми клиентами. Поэтому разумно включить оба: Brotli для современных браузеров, gzip как запасной вариант.
Настройка gzip
Gzip встроен в Nginx. Добавьте в блок http:
gzip on;
gzip_comp_level 5;
gzip_min_length 256;
gzip_vary on;
gzip_proxied any;
gzip_types
text/plain
text/css
text/xml
application/javascript
application/json
application/xml
image/svg+xml;
Что здесь важно:
- gzip_comp_level — от 1 до 9. Выше уровень — больше CPU при небольшом выигрыше в размере. Для сжатия на лету обычно выбирают средние значения.
- gzip_min_length — очень маленькие ответы сжимать бессмысленно.
- gzip_vary — добавляет
Vary: Accept-Encoding, чтобы CDN и прокси не отдали сжатую версию клиенту, который её не понимает. - gzip_proxied any — сжимать ответы и для запросов, пришедших через прокси или CDN.
- text/html в
gzip_typesуказывать не нужно: он сжимается всегда.
Настройка Brotli
Brotli не входит в стандартную сборку Nginx. Нужен модуль ngx_brotli: в части дистрибутивов он есть в виде пакета, иначе его собирают как динамический модуль под вашу версию Nginx. После установки модули подключают в начале nginx.conf:
load_module modules/ngx_http_brotli_filter_module.so;
load_module modules/ngx_http_brotli_static_module.so;
И в блоке http:
brotli on;
brotli_comp_level 5;
brotli_types
text/plain
text/css
text/xml
application/javascript
application/json
application/xml
image/svg+xml;
Если клиент поддерживает оба алгоритма, сработает Brotli; если только gzip — gzip.
Что не нужно сжимать
JPEG, PNG, WebP, AVIF, MP4, WOFF2 и архивы уже сжаты. Повторное сжатие тратит CPU и почти не уменьшает размер. Поэтому указывайте типы явно, а не сжимайте всё подряд.
Предсжатые файлы
Для статики (JS и CSS после сборки) выгоднее сжать файлы заранее с максимальным уровнем, а Nginx будет лишь отдавать готовое:
gzip -k -9 dist/assets/*.js dist/assets/*.css
brotli -q 11 dist/assets/*.js dist/assets/*.css
Рядом с app.js появятся app.js.gz и app.js.br. Включите их отдачу:
gzip_static on;
brotli_static on;
Nginx проверит, есть ли файл с нужным расширением, и отдаст его без сжатия на лету. gzip_static требует модуля ngx_http_gzip_static_module; есть ли он в вашей сборке, покажет nginx -V.
Как проверить
sudo nginx -tиsudo systemctl reload nginx.- Запрос с нужным заголовком:
curl -s -o /dev/null -D - -H "Accept-Encoding: br" https://example.com/assets/app.js
curl -s -o /dev/null -D - -H "Accept-Encoding: gzip" https://example.com/assets/app.js
В ответе ищите content-encoding: br или content-encoding: gzip.
- В DevTools браузера на вкладке Network включите колонку Content-Encoding и сравните переданный и фактический размер файлов.
Частые ошибки
- Нет нужного MIME-типа. Например, API отдаёт
application/json, а его нет вgzip_types. - Модуль Brotli не загружен. Директива
brotliбез модуля даёт ошибку приnginx -t. - Максимальный уровень на лету. Нагружает CPU на каждом запросе; максимум оставьте для предсжатой статики.
- Двойное сжатие. Если backend уже сжимает ответ, а сверху есть CDN, проверьте, на каком уровне это происходит, и оставьте один.