gzip圧縮について調べたまとめ
gzip圧縮について調べたのでまとめる。
概要
圧縮を有効にする | PageSpeed Insights | Google Developers
最新のブラウザはすべて gzip 圧縮に対応しており、すべての HTTP リクエストで自動的に圧縮のネゴシエーションを実施します。gzip 圧縮を有効にすると、転送されるレスポンスのサイズが最大で 90% 削減されるため、リソースのダウンロード時間の大幅な短縮、クライアントのデータ使用量の削減、最初のページ レンダリング時間の改善といった効果があります
概要は上記の説明に任せる。
仕組み
gzip圧縮の恩恵を受けるためにはサーバーとクライアントの両方が圧縮アルゴリズムに対応している必要がある。
クライアントがgzip圧縮を要求する場合は、リクエストヘッダーで Accept-Encoding: gzip
を送る。
そして、サーバーがレスポンスをgzip圧縮し、レスポンスヘッダーで Content-Encoding: gzip
を返す。
実装
サーバーサイド
Node.jsでサーバーサイドの実装をする場合、compressionというミドルウェアがよく使われる。
const compression = require('compression'); const express = require('express'); const app = express(); app.use(compression());
上記のように、app.use
するだけでgzip圧縮されるので簡単。もちろん細かい設定もできる。
クライアント
https://github.com/sindresorhus/got#comparison によると、有名なHTTPクライアントライブラリはどれもgzip圧縮のハンドリングに対応している。
axios
axiosはブラウザからのリクエストにはXMLHttpRequestを利用している。XHRではAccept-Encodingをリクエストヘッダーに設定することが禁止されている。
https://fetch.spec.whatwg.org/#forbidden-header-name
axiosで以下のようなコードを書いた場合、
axios.get("/users", { headers: { "Accept-Encoding": "gzip" } })
ブラウザではコンソールにエラーが出力される。
Refused to set unsafe header "Accept-Encoding"
XHRでのAccept-Encodingヘッダーはユーザーエージェントに委ねられている。
よって、axiosでgzip圧縮されたレスポンスを受け取りたい場合は、Node.jsで動く箇所にだけ Accept-Encoding: gzip
を設定する必要がある。また、decompressオプションをtrueにすることでレスポンスボディを解凍し、Content-Encodingヘッダーを削除する。Content-Encodingヘッダーを削除するのはaxiosで解凍したレスポンスをさらに解凍してしまうのを避けるためだと考えられる。
got
gotでgzip圧縮を利用したい場合はdecompressオプションにtrueを設定する。
https://github.com/sindresorhus/got/blob/main/documentation/2-options.md#decompress
decompressがtrueの場合はAccept-Encodingにgzipを設定している。
また、Content-Encodingがgzipの場合はレスポンスのボディをパースしている。
superagent
https://github.com/visionmedia/superagent/blob/master/docs/index.md#compression
Nodeの場合は何もしなくても圧縮されたレスポンスをサポートしているとある。
HEADメソッドでない場合は、Accept-Encodingにgzipを設定している。
Content-Encodingがgzipの場合はshouldUnzipでtrueが返り、unzipで解凍している。
雑感
- gzip圧縮の仕組みと実装方法を調べた
- サーバーサイドの実装方法は知っていたので、クライアント側の実装方法について重点的に調べた
- 3つのライブラリを調べたが、それぞれgzip圧縮の対応方法が異なり面白かった
- axiosは利用者がAccept-Encodingを渡す必要があり、decompressオプションで解凍するかどうかを制御している
- gotはdecompressオプションでAccept-Encodingの設定と解凍の両方を制御している(headersでAccept-Encodingを渡すこともできそう)
- superagentはデフォルトでAccept-Encodingの設定と解凍をサポートしている