Как стать автором
Обновить

Внедряем Brotli с помощью Nginx — экономим байты почти бесплатно

Время на прочтение 5 мин
Количество просмотров 42K
Эта статья пригодится всем, кто неравнодушен к скорости доставки своего веб-приложения пользователю и хочет выжать дополнительные миллисекунды и килобайты экономии.



Что такое brotli?


Это новый стандарт компрессии данных, разработанный Google. Хорошее описание и сравнение с другими алгоритмами есть у Clouflare.

В двух словах: это новый вид сжатия, который оптимизирован для веб-применений (HTML, CSS, JS и т.д.) за счет использования статического словаря и других оптимизаций. Он показывает сравнимую скорость при лучшем сжатии по сравнению с gzip и намного лучшее сжатие при максимальных настройках (и очень низкой скорости). Подробное исследования скорости и коэффициентов компрессии смотрите в указанной статье от Cloudflare.

Я приведу небольшую таблицу с реальными файлами (JS, CSS) живого веб-сайта. Перед сжатием все файлы были минифицированы. Сравнивать будем zopfli (i500) — совместимый с gzip компрессор и brotli с настройкой сжатия 11 (максимум).
Тип файлов и сжатие Размер (байт) Размер (в % от исходного)
CSS исходные файлы 334 937 100%
CSS zopfli 60 771 18,1%
CSS brotli 56 168 16,7%
JS исходные файлы 477 393 100%
JS zopfli 149 905 31,4%
JS brotli 135 766 28,4%

Из этой таблицы можно прикинуть экономии для варианта использования в static режиме (когда файлы сжаты заранее и отдаются Nginx как есть). Для компрессии динамического контента все немного сложнее — нужно сохранять баланс между степенью компрессии и временем сжатия.

Для себя я вывел следующее правило: за счет zopfli можно сэкономить примерно 10% по сравнению с gzip 9, а brotli даёт еще 10% экономии.

Поддержка браузерами


Достаточно хорошая, чтобы использовать уже сейчас. По данным caniuse.com это около 50% аудитории. На самом деле, думаю побольше, потому что brotli поддерживается в Chrome 51+, Firefox 47+ и мобильным Chrome. Важное дополнение: так как brotli несовместим с gzip, он поддерживается только для HTTPS-ресурсов. Это чтобы всякие тупые прокси не побили контент.

Посмотреть поддержку клиентом просто: он должен указать в заголовке запроса accept-encoding br, что и означает «brotli». Например, так:

accept-encoding: gzip, deflate, sdch, br

Включаем поддержку в Nginx


К сожалению, пока нет стандартного модуля для поддержки brotli в Nginx. Но нас этим не остановишь: есть сторонние модули от самого Google и от Cloudflare. Мы будем использовать вариант от Google, так как он нормально документирован и имеет все нужные возможности.

Здесь нужно определиться, как вы будете использовать brotli: только в статическом варианте (brotli_static) или в динамическом (сжатие на лету — brotli). Сборка модуля в режиме brotli_static проще, так как не требуется библиотека для сжатия brotli: libbrotli.

Используем готовый пакет из PPA


Мы будем использовать Ubuntu 16.04 в качестве сервера. Здесь нам на помощь приходит PPA: https://launchpad.net/~hda-me/+archive/ubuntu/nginx-stable. Из PPA мы получаем Nginx Stable ветки с множеством дополнительных модулей. Большинство из них динамические, то есть их можно подключать по желанию. Если вас устраивает этот вариант, можете ставить и переходить к конфигурации.

Собираем Nginx самостоятельно


В этом случае процесс аналогичен сборке Nginx с любыми другими модулями. Сначала качаем и распаковываем исходники Nginx (указана актуальная на момент публикации версия).

wget https://nginx.org/download/nginx-1.11.4.tar.gz

Получаем код модуля ngx_brotli:

git clone https://github.com/google/ngx_brotli.git

Если мы хотим использовать brotli в динамическом режиме, качаем libbrotli:

git clone https://github.com/bagder/libbrotli.git

И собираем (в папке libbrotli):

./autogen.sh
./configure
make

Или можем установить libbrotli из PPA, указанного ранее.

sudo add-apt-repository ppa:hda-me/nginx-stable
sudo apt-get update
sudo apt-get install libbrotli

Если нам нужен только brotli_static, перед сборкой Nginx говорим об этом:

export NGX_BROTLI_STATIC_MODULE_ONLY=1

Теперь идём в папку с исходниками Nginx и собираем его (c опцией --add-module=[путь до ngx_brotli]):

./configure --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-http_ssl_module --with-http_realip_module --with-http_addition_module --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_stub_status_module --with-http_auth_request_module --with-http_xslt_module=dynamic --with-http_image_filter_module=dynamic --with-http_geoip_module=dynamic --with-http_perl_module=dynamic --with-threads --with-stream --with-stream_ssl_module --with-stream_geoip_module=dynamic --with-http_slice_module --with-mail --with-mail_ssl_module --with-file-aio --with-ipv6 --with-http_v2_module --with-cc-opt='-g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,--as-needed' --add-module=/home/db/ngx_brotli

make

Далее можно установить Nginx (make install) или собрать в deb-пакет:

sudo checkinstall --pkgname=nginx --pkgversion=1.11.4 --nodoc

Конфигурация Nginx


Итак, у нас наконец есть Nginx с поддержкой brotli. Для использования статических brotli-файлов (сжатых заранее), достаточно включить в конфиг nginx.conf (секция http) одну директиву:

brotli_static	on;

Теперь nginx будет искать версию файла с суффиксом .br, если клиент заявляет о поддержке brotli. Если не найдёт, то будет работать модуль gzip_static (если включён).

Для активации динамического режима указываем следующие параметры:

brotli		on;
brotli_comp_level	6;
brotli_types	text/plain text/css text/xml application/x-javascript;

Здесь мы используем уровень сжатия 6, потому что он имеет хорошее соотношение качество/производительность. Уровень сжатия будет лучше, чем с gzip 9. Далее указаны MIME-типы контента для сжатия. Уточните конфигурацию ваших MIME-типов на сервере, чтобы сжатие применялось к нужным типам контента. Brotli имеет приоритет перед gzip, поэтому будет использоваться в случае поддержки (также для статического режима).

Проверить работу brotli просто: посмотрите на заголовки ответа, там должно быть:

content-encoding:br

На этом всё: успехов в оптимизации и используйте новые технологии!

P. S. Если вы используете Ubuntu 16.04, то установить утилиту для консольного сжатия brotli очень просто:

sudo apt-get install brotli
Теги:
Хабы:
+24
Комментарии 4
Комментарии Комментарии 4

Публикации

Истории

Ближайшие события

Московский туристический хакатон
Дата 23 марта – 7 апреля
Место
Москва Онлайн
Геймтон «DatsEdenSpace» от DatsTeam
Дата 5 – 6 апреля
Время 17:00 – 20:00
Место
Онлайн
PG Bootcamp 2024
Дата 16 апреля
Время 09:30 – 21:00
Место
Минск Онлайн
EvaConf 2024
Дата 16 апреля
Время 11:00 – 16:00
Место
Москва Онлайн