nginx+W3 Total Cache+gzipでのVaryヘッダー嵌りどころメモ【WordPress・Brotli】

 last update 2024年6月6日

これまた、需要の少ない情報になるわけですが、自分用メモ。

nginx + PHP-FPM + WordPress + W3 Total Cache(以下、W3TC)環境下で、W3TC における gzip・Brotli の圧縮設定と Vary ヘッダ制御のベストプラクティス(言い過ぎ)について考察。

さぞかし分かりにくい題材であろうから、見出しのスクショ絡みの設定だよ、とだけ。ここまで聞いただけでピンと来る人向けの記事。

多分、検索でこの記事に辿りつけた人は、W3TC で SP・PC 版の HTML を出し分けまではしたものの、HTTP ヘッダに吐かれる Vary: Accept-Encoding; をどうにかして Vary: Accept-Encoding,User-Agent; に書き換えたいのであろうから、その前提にて。

答えの前に、前提知識を少し補足しておく。

W3TC でブラウザーキャッシュの gzip・Brotli 圧縮を有効化した場合、WordPress ルート上の nginx.conf には gzip on;brotli on; など圧縮絡みの記述が出力される。

つまり、この構成において W3TC は nginx の gzip・Brotli 圧縮機能を当てにしており、出力される Vary: Accept-Encoding; ヘッダは W3TC 由来の設定に基づき nginx が吐いている構図となる。

ここで重要なのは、当該ヘッダが PHP でなく直接的には nginx により出力されているヘッダである、という点。

だから、WordPress の functions.php で wp_headerssend_headers といったフィルターフックを駆使して

  • $headers['Vary'] = 'Accept-Encoding,User-Agent';
  • unset($headers['Vary']);
  • header('Vary: User-Agent');

と頑張ったところで、一生 HTTP ヘッダは編集できない。(この構成において低位レイヤーで Vary ヘッダが出力されていると、PHP から Vary ヘッダは触れない )

さらに悪いことに、nginx で gzip_vary on; を指定すると、HTTPヘッダに Vary: Accept-Encoding;強制出力される仕様も、今回のような PHP での Vary ヘッダ制御問題に絡んでくる。

答えの1つにはなるのだけども、このケースでヘッダを上書きするには、nginx 拡張モジュール「headers-more-nginx-module」の more_set_headers ディレクティブを使うこととなる。

(※余談にはなるが、nginx の gzip 関連ヘッダ周りの仕様に関しては、誤った設定をされないよう保守的になっているのかもしれない。Content-Encoding ヘッダと圧縮済みペイロードを巡っては、ミドルボックスで酷い扱いを受けた歴史的経緯があるので。)

nginx で more_set_headers が使える環境なら Vary ヘッダをお目当てどおりに書き換える手もあるが、そうでなければ、こうしてめでたく nginx でも PHP でも編集できない Vary ヘッダが出来上がるワケ。

で、ココからがようやく解決策。オプションは2つある。

1つ目は、Vary ヘッダを重複出力する方法。仕様上、Vary ヘッダは複数吐き出しても問題ない(※カンマで繋いで正しい内容になるなら)ので、W3TC(nginx)が勝手に吐く Vary: Accept-Encoding; はそのままに、nginx の追加設定で Vary: User-Agent; を常時、あるいは必要な条件のときだけ出力する。

個人的にはこれが最もプレーンな解決策と思う。

単純に add_header で追加出力するだけだと Vary: User-Agent; が重複するなどして見栄えが悪くなるケースがある。でも、先の more_set_headers で更新したり、W3TC の変数で分岐すれば体裁はそこそこ整えられる。

そして2つ目は、gzip 圧縮を nginx 側のみで完結し、W3TC の gzip・brotli 圧縮設定はすべて OFF にする方法。ちゃんと nginx 側で gzip_vary off; にして Vary ヘッダが一切出力されない状態なら WordPress・PHP 側からでも Vary ヘッダを出力できる。もちろん、その状態で「1」同様に nginx 側から Vary ヘッダを出力する手もある。

どうしても WordPress 側だけで完結して Vary ヘッダを制御したいならこういう形態も取れなくもない。

ただしこの方法には欠点があり、恐らくはサーバーレスポンスへの悪影響がある。というのも、W3TC のページキャッシュや Minify が gzip・brotli 圧縮済みリソースキャッシュしているからだ。

いずれの場合も、W3TC のユーザーエージェントグループで指定したテーマで Vary: Accept-Encoding,User-Agent,Cookie; というド派手なヘッダが出力されるのは気になるかもですが。

さて、あまりに長くなったので、ここまで読んでいただいた方向けにお土産を置いておきましょう。

実は W3TC のブラウザキャッシュで brotli 圧縮設定を on にするには PHP Extension である php-ext-brotli の有効化が必要。つまり、勘の良いエンジニアならもうお気づきのとおり、W3TC はそれ自身がペイロード圧縮と圧縮済みリソースのキャッシュとを同時に担えるわけ。そうなればもう、最適な構成・設定は自ずと決まってきます。

とまぁ、敢えて目次も付けず、内容も要約に終始したわけですが、そのものズバリでなくとも、何かしらの気付きが得られるキッカケになれば幸いです。

Hatena Pocket Line

コメントを記入