2026年10月12日

2026年10月12日

WordPressのNginxでgzip圧縮とHTTP/2を有効化する設定手順

Nginx で動かしている WordPress は、gzip 圧縮と HTTP/2 を有効にするだけで、HTML・CSS・JavaScript の転送量と接続のむだを減らせます。この記事では、どのファイルにどう書くか、Nginx のバージョンによる書き方の違い、設定が効いているかを curl で確かめる方法、よくあるつまずきまでを順に説明します。

作業前の確認

最初に Nginx のバージョンと、組み込まれているモジュールを確認します。HTTP/2 の書き方はバージョンで変わるためです。

nginx -v
nginx -V 2>&1 | tr ' ' '\n' | grep -E 'http_v2|gzip_static|openssl'

--with-http_v2_module が表示されれば HTTP/2 が使えます。ディストリビューションの公式パッケージや nginx.org のパッケージであれば、多くの場合は最初から含まれています。表示された OpenSSL のバージョンも見ておきます。HTTP/2 はブラウザとの間で ALPN という TLS の仕組みを使って合意するため、極端に古い OpenSSL では使えません。

もう一つの前提は HTTPS です。HTTP/2 の仕様自体は平文でも定義されていますが、主要なブラウザは TLS 上の HTTP/2 にしか対応していません。まだ証明書を設定していない場合は、先に Let's Encrypt などで HTTPS 化を済ませてください。

設定を変える前には、編集するファイルのバックアップを取ります。

sudo cp -a /etc/nginx /etc/nginx.bak-$(date +%Y%m%d)

gzip 圧縮を設定する

gzip の設定は http ブロックに書くと全サイトに効きます。Debian/Ubuntu 系の nginx.conf には gzip 関連の行がコメントアウトされた状態で入っていることが多いので、重複しないように整理しつつ、/etc/nginx/conf.d/gzip.conf のような別ファイルにまとめると管理しやすくなります(conf.d が http ブロック内で読み込まれていることを確認してください)。

# /etc/nginx/conf.d/gzip.conf(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
    application/rss+xml
    application/atom+xml
    image/svg+xml
    font/ttf
    font/otf;

各項目の意味は次のとおりです。

  • gzip_comp_level:1〜9 の圧縮レベル。上げるほど小さくなりますが CPU を使い、5〜6 を超えると縮み方の伸びは小さくなります。まずは 5 前後から始めるのが無難です
  • gzip_min_length:これより小さいレスポンスは圧縮しません。数百バイトの応答は圧縮しても効果が薄いためです
  • gzip_vary:Vary: Accept-Encoding を付け、CDN やプロキシが圧縮版と非圧縮版を取り違えないようにします
  • gzip_proxied any:CDN やロードバランサー経由のリクエストにも圧縮を行います
  • gzip_types:圧縮する MIME タイプ。text/html は既定で常に圧縮対象なので書く必要はありません。書くと nginx -t で重複の警告が出ます

JPEG・PNG・WebP・AVIF の画像や、WOFF2 フォント、ZIP などはすでに圧縮された形式なので、gzip_types に入れても小さくならず CPU を使うだけです。テキスト系に絞るのが基本です。

PHP 側の圧縮と重ねない

php.ini の zlib.output_compression や、キャッシュ系プラグインの「gzip 圧縮」機能を有効にしていると、PHP とNginx の両方で圧縮の処理を持つことになり、問題の切り分けが難しくなります。Nginx は Content-Encoding がすでに付いたレスポンスを二重には圧縮しませんが、どこで圧縮しているかを1か所にそろえておくと、トラブル時に原因を追いやすくなります。Nginx で圧縮するなら、PHP とプラグイン側の圧縮は切っておくのがおすすめです。

事前圧縮(gzip_static)という選択肢

ngx_http_gzip_static_module が組み込まれていれば、style.css.gz のようにあらかじめ圧縮したファイルを置いておき、gzip_static on; でそれをそのまま返すこともできます。リクエストごとの圧縮処理が不要になる一方、元ファイルを更新したら .gz も作り直す運用が必要です。テーマやプラグインの更新が頻繁なサイトでは、動的な gzip だけで十分なことが多いでしょう。

HTTP/2 を有効にする

HTTP/2 の書き方は Nginx 1.25.1 を境に変わりました。1.25.1 以降は server ブロックで http2 on; を使います。

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    http2 on;
    server_name example.com;

    ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    root /var/www/wordpress;
    index index.php;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }
    # PHP-FPM への受け渡しなど、既存の設定はそのまま残す
}

1.25.0 以前では listen 443 ssl http2; のように listen の引数で指定します。1.25.1 以降でもこの書き方は動きますが、非推奨の警告が出るため、バージョンを上げたら http2 on; に書き換えておくと後で困りません。

同じ IP とポートで複数のサイトを動かしている場合、旧来の listen ... http2 の書き方はそのアドレスとポートを共有するすべてのサイトに効く点に注意してください。あるサイトだけ HTTP/2 を外したつもりでも、ほかのサイトの listen に引きずられることがあります。http2 on; はサイト(server ブロック)ごとに指定できるよう追加された書き方です。

かつて使われた HTTP/2 サーバープッシュ(http2_push)は、主要ブラウザが対応をやめ、Nginx でも 1.25.1 で廃止されています。古い記事を見て設定すると、新しい Nginx では起動エラーになるので使わないでください。重要なリソースを早く読ませたい場合は、<link rel="preload"> や 103 Early Hints など別の手段を検討します。

反映と確認

設定を書いたら、構文チェックを通してから再読み込みします。restart ではなく reload なら、接続中のリクエストを切らずに設定を入れ替えられます。

sudo nginx -t && sudo systemctl reload nginx

確認は curl で行います。gzip は Accept-Encoding を送ったときに Content-Encoding: gzip が返るかを見ます。

# HTML の圧縮を確認
curl -sI -H 'Accept-Encoding: gzip' https://example.com/ | grep -iE 'content-encoding|vary'

# CSS の圧縮を確認(パスは実際のテーマに合わせる)
curl -sI -H 'Accept-Encoding: gzip' https://example.com/wp-content/themes/your-theme/style.css | grep -i content-encoding

# HTTP/2 で応答しているか確認
curl -sI --http2 https://example.com/ | head -n 1

最後のコマンドで HTTP/2 200 と表示されれば HTTP/2 で通信できています。ブラウザでは開発者ツールのネットワークタブでプロトコル列を表示すると h2 と確認できます(列の表示方法はブラウザにより異なります)。

うまくいかないときの確認ポイント

  • Content-Encoding が付かない:MIME タイプが gzip_types に無い、レスポンスが gzip_min_length より小さい、設定ファイルが http ブロックで読み込まれていない、のいずれかが多い原因です。nginx -T で実際に読み込まれている全設定を表示して確認できます
  • CDN 経由だと結果が違う:Cloudflare などの CDN を使っている場合、ブラウザが受け取るのは CDN が圧縮・配信したものです。オリジンの設定を確かめるときは、hosts を書き換えるか curl の --resolve でオリジンに直接つないで確認します
  • HTTP/2 にならない:listen の 443 に ssl が付いていない、別の server ブロックの listen と食い違っている、古い Nginx で http2 on; を書いて構文エラーになっている、などを nginx -t の出力で確認します
  • 警告「duplicate MIME type "text/html"」:gzip_types から text/html を外せば消えます

圧縮率をさらに上げたい場合は Brotli という選択肢もありますが、Nginx 標準には含まれず、別途モジュールを組み込む必要があります。また Nginx は 1.25 系から HTTP/3(QUIC)にも対応していますが、UDP の開放などの準備が別に必要です(2026年10月現在)。まずは gzip と HTTP/2 が期待どおり動いていることを確かめてから検討するとよいでしょう。

まとめ

  • gzip は http ブロックに設定し、圧縮対象はテキスト系の MIME タイプに絞る。text/html は既定で対象
  • 圧縮レベルは 5 前後から始め、PHP やプラグインの圧縮とは重ねない
  • HTTP/2 は HTTPS が前提。Nginx 1.25.1 以降は http2 on;、それ以前は listen の引数で指定する
  • サーバープッシュは廃止済みなので設定しない
  • nginx -t で構文を確かめてから reload し、curl でヘッダーとプロトコルを確認する

お気軽にご相談ください

お見積りへ お問い合わせへ
▲