Пересборка Nginx с поддержкой Brotli

Feb 6, 2017 21:07 · 513 words · 3 minute read nginx brotli

Мы уже знаем, как включить HTTP2.0 в Nginx и умеем собирать Nginx с поддержкой ALPN (Application-Layer Protocol Negotiation) для браузера Chrome.

Эта статья пригодится всем тем, кто неравнодушен к скорости доставки своего приложения пользователю, кто борется за миллисекунды и килобайты — давайте разберемся!

В двух словах: Brotli — алгоритм сжатия данных, основанный на более современном варианте алгоритма LZ77. Brotli был разработан и представлен компанией Google в 2015 году как специализированный алгоритм для сжатия веб-шрифтов. В дальнейшем была представлена версия brotli, которая содержала улучшения направленные на сжатие всего интернет-трафика (HTML, CSS, JS). Поддержка данного алгоритма по умолчанию включена в Chrome 49+, Firefox 44+, Opera 36+ и мобильном Chrome. Больше информации и сравнение с остальными алгоритмами сжатия можно найти тут.

Примечание. Важное дополнение: так как brotli несовместим с gzip, он поддерживается только для HTTPS-ресурсов, чтобы всякие тупые прокси не побили контент.

Проверить поддержку brotli клиентом легко: в заголовке запроса accept-encoding должно быть br (что означает brotli), например так:

accept-encoding: gzip, deflate, sdch, br

На сегодняшний день официального модуля для поддержки Brotli в Nginx нет, поэтому будем все делать руками.

Сначала стоит определиться, как будем использовать brotli: в статическом варианте (brotli_static, файлы сжаты заранее и отдаются Nginx как есть) или в динамическом (brotli, сжатие на лету). Собрать модуль в статическом режиме проще, поэтому мы рассмотрим сборку модуля для динамического режима работы.

Скачиваем и распаковываем исходники актуальной версии Nginx:

cd /opt/
wget https://nginx.org/download/nginx-1.11.9.tar.gz
tar xf nginx-1.11.9.tar.gz

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

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

Далее выполняем:

cd /opt/ngx_brotli && git submodule update --init && cd /opt/nginx-1.11.9

иначе при сборке Nginx столкнемся с ошибкой:

...
adding module in /opt/ngx_brotli

./configure: error: Brotli library is missing from the /opt/ngx_brotli/deps/brotli directory.
...

Находясь в каталоге с исходниками Nginx собираем его (не забываем про поддержку APLN):

./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_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-threads \
    --with-stream \
    --with-stream_ssl_module \
    --with-http_slice_module \
    --with-mail \
    --with-mail_ssl_module \
    --with-file-aio \
    --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' \
    --with-openssl=/opt/openssl-1.0.2j \
    --add-module=/opt/ngx_brotli
make
make install
service nginx restart

Теперь, когда у нас собран Nginx с поддержкой brotli, необходимо внести несколько изменений в конфигурационные файлы web-сервера. Если вы решили использовать brotli в статическом режиме, то для его активации достаточно добавить одну директиву в секции http конфига /etc/nginx/nginx.conf:

...
brotli_static on;
...

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

В нашем случае brotli используется в динамическом режиме (сжатие на лету), поэтому директив будет чуть больше:

...
brotli    on; # включаем brotli
brotli_comp_level 6; # уровень компрессии от 1 до 11
brotli_types  text/plain
              text/css
              text/xml
              application/x-javascript; # MIME-типы контента для сжатия
...

Когда brotli включен, он получает приоритет над gzip, следовательно gzip‘ом данные будут сжиматься только если браузер не поддерживает brotli.

Проверить, все ли правильно сделано можно тут.

tweet Share