WordPressのサイトをCloudFrontで圧縮転送しようとすると動かない問題を解決

AWS

一定条件を満たさないと、gzip等での圧縮転送が有効にならない

ドキュメントを見ると、一定条件を満たさないと、圧縮転送が有効になりません。

圧縮ファイルを供給する - Amazon CloudFront
圧縮ファイルを供給してユーザーが高速にダウンロードできるようにします。

 

以下の文章ですね。

  • ファイルは CloudFront が圧縮するタイプである必要があります。詳細については、「CloudFront が圧縮するファイルタイプ」を参照してください。
  • ファイルサイズは 1,000 ~ 10,000,000 バイトの間である必要があります。
  • 応答には Content-Length ヘッダーを含めて、ファイルのサイズが CloudFront の圧縮範囲に含まれるかどうかを CloudFront が判断できるようにする必要があります。Content-Length ヘッダーがない場合、CloudFront はファイルを圧縮しません。

 

何が原因か

今回の案件で、WordpressをCDNでキャッシュしているのですが、どうにも圧縮転送が有効にならない、という症状がありました。

調べてみると、Wordpressを実行、、、というかPHPで吐き出されたHTMLは自動ではContentLengthがレスポンスヘッダに追加されないようなのです。意図的にコンテンツの長さを取得して、headerなどで出力しないとだめみたいです。

 

対応

function.phpに以下を追加して、今回は回避しました。

add_action( 'init', 'process_post' );
function process_post() {
     ob_start();
}

add_action('shutdown', function() {
    header('Content-Length: '.ob_get_length());
    ob_end_flush();
}, 0);

一番はじめにob_startして、終了直前にob_get_lengthで長さを出力、ob_end_flushで本文を出力。みたいな感じです。

 

今回はこれで一旦動きましたが、プラグイン(キャッシュ系)のプラグインやnginx/Apacheの設定しだいでは動かない可能性もあります。

 

こちらにも回避情報がありました。ありがとうございます。

WordPress サイトを CloudFront で配信すると compress オプションを設定していても圧縮転送されない... - dogmap.jp
タイトルで言い切ってますが… CloudFront の「Compress Objects Automatically」ってオプションを有効にすると、対応しているブラウザに対しては圧縮転送をしてくれるはずなんで

 

それぞれ適した方法で、Content-Lengthを出力してあげてください。参考になればと思います。

 

回避して思ったのですが、あんまりWordpressで出力したコンテンツ本体をCDNでキャッシュとか向かないのかな。と思ったりしました。nginxのfast_cgi_cacheとかで対応できる範囲なら、ソッチのほうが、、