NginxでBrotliによるコンテンツのデータ圧縮を行う

いまさらだけどBrotliの圧縮機能ををNginxで有効にすることにした。

環境は例によってFreeBSDでNginxやBrotliはportsでインストールすることにする。

Brotliモジュール付きNginx portsの更新/インストール

# cd /usr/ports/www/nginx-devel  #使用中orインストールしたい方のports
または
# cd /usr/ports/www/nginx        #使用中orインストールしたい方のports

Nginxを新規でインストールする場合
# make install

既にportsのNginxを利用している場合
# make config
# portupgrade -f www/nginx-devel  #以下2行のどちらか
# portupgrade -f www/nginx

Nginx portsのmake config
make install (新規)または make config (更新)を実行するとビルドオプションが表示されるので BROTLI にチェックする。(カーソルキーで行を合わせて[Space]など)

更新の場合はmake configの代わりに /var/db/ports/www_nginx-devel/options か /var/db/ports/www_nginx/optionsをエディタで開いて OPTIONS_FILE_UNSET+=BROTLI の行をOPTIONS_FILE_SET+=BROTLI に変更して保存するでも可。

BROTLIを有効にしてビルドすると自動的にarchivers/brotliのportsがインストールされる。

なお、portsでインストールされるNginx用のBrotliモジュールはngx_brotliのようなので設定の詳細はそちらから。

Nginxの設定

/usr/local/etc/nginx/nginx.conf (設定追加)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
load_module /usr/local/libexec/nginx/ngx_http_brotli_filter_module.so;
load_module /usr/local/libexec/nginx/ngx_http_brotli_static_module.so;

中略

http {

   中略

   gzip                 on;
   gzip_http_version    1.0;
   gzip_static          on;
   gzip_min_length      100;
   gzip_buffers         16 8k;
   gzip_vary            on;
   gzip_comp_level      1;
   gzip_types           application/atom+xml
                        application/javascript
                        application/rss+xml
                        application/x-javascript
                        application/xml
                        application/xml+rss
                        image/svg+xml
                        text/css
                        text/javascript
                        text/plain
                        text/xml;

    brotli              on;
    brotli_comp_level   6;
    brotli_static       on;
    brotli_types        application/atom+xml
                        application/javascript
                        application/rss+xml
                        application/x-javascript
                        application/xml
                        application/xml+rss
                        image/svg+xml
                        text/css
                        text/javascript
                        text/plain
                        text/xml;

    中略

    }

中略

}

Brotliモジュールは自動では使用されない筈なので設定ファイルの最初でロードさせる。

brotliモジュールの設定はgzip圧縮の設定と似た感じ。brotli_staticをオンにした場合は静的なbrotli圧縮ファイルを用意する。これはgzip_staticと同様。
全てのブラウザでbrotli圧縮が使えるわけではないのでgzip圧縮も(これまで有効にしていたなら)有効のままににしておく。

静的コンテンツを圧縮

静的ファイルをBrotliで圧縮する。

/PATH/index.htmlをbrotliで圧縮する実行例
$ /usr/local/bin/brotli /PATH/index.html --force --output=/PATH/index.html.br
または
$ /usr/local/bin/brotli -f /PATH/index.html

圧縮レベル ( -q 値 ) は0〜11で11が最も高い圧縮率。未指定で6。おそらく未指定で良いかと。
-f または --forceオプションで出力ファイルは上書きされる。コンテンツを更新して再圧縮する場合などに有用。
-s または --suffixオプションは初期値が.br なので上の実行例の1つめと2つめは同じ結果となる。(出力ファイル名は「元のファイル名.br」で既に存在する場合は上書き)

ウェブサイトのファイルは殆どの場合に大量に存在する筈なので1つ1つ手作業で圧縮するのは非常に手間。更新したときの再圧縮も面倒でイヤになる筈。指定したディレクトリ内のファイルを一気に(下層も再帰的に)圧縮するスクリプトを用意する。

brotli.sh
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
#!/usr/bin/env bash
if [ $# -ne 1 ]; then
    echo "usage: brotli.sh /Path"
    exit 1
fi

for FILE in $(find $1 -type f  -iname "*.html" -o -iname "*.xml" -iname "*.css" -o -iname "*.js" -o -iname "*.svg" ); do
    echo -n "${FILE}..."
    /usr/local/bin/brotli ${FILE} --force --output=${FILE}.br;
    echo "done."
done

指定されたディレクトリ内のファイルを順番に処理。拡張子が html, xml, css, js, svg のファイルならbrotliで圧縮するというもの。


使い方:
$ brotli.sh /usr/local/www/example
 

圧縮したいディレクトリのPathを引数に指定して実行

Nginxの設定確認と再起動

# service nginx configtest    #設定確認 これは稼働中のNginxに影響しない
Performing sanity check on nginx configuration:
nginx: the configuration file /usr/local/etc/nginx/nginx.conf syntax is ok
nginx: configuration file /usr/local/etc/nginx/nginx.conf test is successful

# service nginx restart
または
# service nginx gracefulstop && service nginx start
または
# service nginx reload

設定確認でtest is successfulになるまではNginxを再起動させない。設定が不完全で下手に再起動させようとするとサービス停止になる。

Brotli圧縮の動作確認

# 圧縮無し
% curl -I https://example.com/index.html
HTTP/2 200
server: nginx
date: Fri, 13 Apr 2018 04:22:00 GMT
content-type: text/html; charset=utf-8
content-length: 12270                             #←コンテンツサイズ
last-modified: Sun, 11 Feb 2018 14:04:55 GMT
vary: Accept-Encoding
etag: "5a804d87-2fee"
expires: Fri, 13 Apr 2018 04:22:00 GMT
cache-control: max-age=0
strict-transport-security: max-age=31536000;
accept-ranges: bytes

# Brotli圧縮
% curl -H "Accept-Encoding: br" -I https://example.com/index.html
HTTP/2 200
server: nginx
date: Fri, 13 Apr 2018 04:19:51 GMT
content-type: text/html; charset=utf-8
content-length: 2673                             #←コンテンツサイズ
last-modified: Sun, 11 Feb 2018 14:04:55 GMT
vary: Accept-Encoding
etag: "5a804d87-a71"
content-encoding: br                             #←Brotli圧縮
expires: Fri, 13 Apr 2018 04:19:51 GMT
cache-control: max-age=0
strict-transport-security: max-age=31536000;

正しく機能していれば圧縮されたコンテンツが取得されるのでコンテンツサイズが小さい筈。

ウェブツールでも確認してみる。

Brotli Test
https://tools.keycdn.com/brotli-testでBrotli Testを実行できる。URL (静的コンテンツ)を入力して[Test]をクリックして薄緑の四角の部分に「Yeah! [入力したURL] suppors Brotli compression.」が表示されればOK.シンプルに「Brotli compression is supported.」になったらしい。

2021年11月17日:
最後のtools.keycdn.comのオンラインツールでの確認画像が失われていたため新しい画像に差し替え。