CloudFrontでgzip圧縮したデータを転送する
2015/12 追記
2015年12月にCloudFront Distributionの設定でエッジでgzip圧縮を行うことができるようになりました。便利!
(以下、2013年8月時点での記事となります)
HTMLやCSSはgzipで圧縮して転送したいもの。ということで、CloudFrontでgzip転送する方法を確認したところ、簡単にできる感じでもなかったので軽くまとめる。 ドキュメントはここ
クライアントが Accept-Encoding: gzip をヘッダに含めてリクエストしてきたときのみに圧縮したデータを返却することができる。gzipのみ対応しており、deflateやsdchを指定されても無視する。
とはいえ Accept-Encoding を指定するだけで圧縮してくれるわけではない。これは、そのコンテンツを圧縮すべきかどうかの判断をする術がCloudFront側にないため。(圧縮率が悪いデータを圧縮・展開してもオーバーヘッドがかかるだけ、最悪サイズが増加してしまう場合もあって、一律圧縮するというのは効率がよくありません。)
オリジン側の対応についてみていく。
S3以外のカスタムオリジンの場合
オリジンをS3以外のApacheやNGINXなどのWebサーバを使う場合。
- webサーバ側でどのコンテンツを圧縮するか決めて設定する。拡張子を見て圧縮させるようなディレクティブを書いたりする
- ふつうにCloudFrontのディストリビューションを作成する
- webブラウザがCloudFrontのエッジにリクエストを飛ばす
- エッジはAccept-Encoding: gzipのヘッダがあれば、圧縮バージョンのキャッシュを探し、そうでなければ無圧縮のキャッシュを探す
- キャッシュがあればそれをwebブラウザに応答し、なければオリジンにリクエストを投げる
- エッジからのリクエストで、Accept-Encoding: gzipで且つ、上で圧縮対象にしたコンテンツならば圧縮されたデータを返却し、エッジにキャッシュされる
CloudFrontのエッジでは、圧縮されたものと、無圧縮なものと2パターンのキャッシュを保持するようになる感じ。Webサーバの設定は特に面倒なものではない。
S3がオリジンの場合
動的な生成などがなければ、S3をオリジンにすることが多いと思うのですが、カスタムオリジンよりも設定が面倒です。
- 圧縮対象のコンテンツについて、圧縮したものと、無圧縮のものと各2種類ずつデータを用意する。welcome.js があるとして、その圧縮版は welcome.js.gz。
- 両方をS3にアップロードする
- 圧縮したファイルについては、Content-Encoding: gzip のヘッダをManagement Consoleなどでつける
- 動的に生成するHTMLからCloudFrontへのリンクをする際に、クライアントが Accept-Encoding: gzip をヘッダに乗せてきたら welcome.js.gz の方を参照させる。
ということで、S3側はAccept-Encodingに応じて圧縮するとかそういった処理を行わないので、HTML生成時に動的にリンク先を変えろということ。
まとめ
- CloudFrontは動的にgzip圧縮するようなことはなく、圧縮済みのデータを持たせることで対応する
- S3をオリジンとした場合、Accept-Encodingを見て圧縮済みか未圧縮のデータを返すかという処理ができない
まだ続きます。。