HTTP の圧縮

圧縮は、ウェブサイトのパフォーマンスを向上させるための重要な手段です。文書によっては、必要な帯域を最大 70% 削減するほどサイズが縮減します。長年かけてアルゴリズムはより効率的になり、またクライアントおよびサーバーが新たなアルゴリズムに対応してきました。

実際のところ、圧縮の仕組みはブラウザーやサーバーがすでに実装していますので、ウェブ開発者が実装する必要性はありません。しかし、サーバーが適切に設定されるように注意しなければなりません。圧縮は、3 種類の異なるレベルで実施します。

  • 始めに、一部のファイル形式は、固有の最適化された方法で圧縮されます。
  • そして、一般的な暗号化が HTTP レベルで行われれる場合があります(リソースはエンドツーエンドで圧縮されて転送されます)
  • 最後に HTTP コネクションの 2 つのノード間で、コネクションレベルで圧縮が定義される場合があります。

ファイル形式の圧縮

それぞれのデータ形式には、無駄なスペース (wasted space) と呼ばれる冗長な領域が内部にあります。テキストは一般的に 60% もの冗長性を持つものであり、この割合は音声や動画といった他のメディアよりはるかに高くなります。テキストとは異なり、これらのその他のメディア形式はデータを格納するためにより多くの領域を使用するので、ストレージを最適化し領域を取り戻す必要性はごく初期に明らかになりました。技術者は特定の用途向けに設計されたファイル形式で使用される、最適化された圧縮アルゴリズムを設計しました。メディアファイルで使用される圧縮アルゴリズムは、大きく 2 つのカテゴリーに分類できます。

  • 可逆圧縮。圧縮・展開のサイクルで取り出したデータが変化しません。これは元のデータに(バイト単位で)一致します。 画像では gifpng が可逆圧縮を使用しています。
  • 非可逆圧縮。圧縮・展開のサイクルにおいて、ユーザーが(できるだけ)認知できない方法で元のデータを変更します。 ウェブ上の動画形式は非可逆です。 jpeg 画像も非可逆です。

webp のように可逆圧縮と非可逆圧縮のいずれかを使用できる形式もありますが、通常は非可逆圧縮で高圧縮・低圧縮を設定でき、当然ながらそれは品質の高低に結びつきます。サイトのパフォーマンスを高めるには、満足できる品質レベルを維持しながら、できるだけ圧縮することが理想です。画像の場合は、ツールが生成する画像はウェブ向けに十分最適化されていない場合があります。要求する品質で可能な限り圧縮するツールを使用することをお勧めします。この用途に特化した多くのツールがあります。

非可逆圧縮アルゴリズムは一般的に、可逆圧縮より効率がよくなります。

メモ: 特定の種類のファイルは圧縮が良好に機能しているため、通常は 2 度目の圧縮を行いません。実際のところ、大きなファイルの圧縮によって得られる追加の利益よりもオーバーヘッド (アルゴリズムは一般的に、初期のサイズに追加する辞書が必要です) のコストが上回る場合があります。圧縮済み形式のファイルで、以下の 2 つの技術は使用しないでください。

エンドツーエンドの圧縮

エンドツーエンドの圧縮は、ウェブサイトのパフォーマンスをもっとも向上させます。エンドツーエンドの圧縮は、サーバーによって行われるメッセージ本体の圧縮を指しており、圧縮されたデータはクライアントに到達するまで変更されません。中間のノードはすべて、本体部分に手をつけないままにします。

圧縮された HTTP 本体をネットワークノード経由でクライアントに送信するサーバー。本体がクライアントにリーチするまで、ネットワーク上のどのホップでも展開されません。

現代のすべてのブラウザーやサーバーはこの圧縮をサポートしており、唯一取り決めることは、使用する圧縮アルゴリズムです。これらのアルゴリズムは、テキストに最適化されています。1990 年代に圧縮技術は速いペースで進歩して、いくつものアルゴリズムが、使用可能な選択肢に追加されました。現在妥当なアルゴリズムは、もっとも一般的な gzip と新たな挑戦者である br の 2 つだけです。

使用するアルゴリズムを選択するには、ブラウザーとサーバーでプロアクティブなコンテンツネゴシエーションを行います。ブラウザーは Accept-Encoding ヘッダーで、サポートするアルゴリズムを優先度順に並べて送信します。サーバーはそのうちひとつを選択して、レスポンスの本体の圧縮に使用します。そして Content-Encoding ヘッダーを使用して、選択したアルゴリズムをブラウザーに伝えます。エンコーディングに基づいて表現を選択するためにコンテンツネゴシエーションを使用したとき、少なくとも Content-Encoding を含めた Vary ヘッダーを、レスポンスとともに送信しなければなりません。この方法によって、リソースのさまざまな表現をキャッシュすることができます。

'Accept-Encoding: br, gzip' ヘッダーでコンテンツをリクエストされたクライアント。サーバは Brotli アルゴリズムで圧縮した本体と、必要な 'Content-Encoding' ヘッダーと 'Vary' ヘッダーでレスポンスします。

圧縮によってパフォーマンスが大きく向上しますので、画像・音声・動画といったすでに圧縮されているものを除くすべてのファイルで圧縮を有効化することを推奨します。

Apache は圧縮や mod_deflate をサポートします。 Nginx では ngx_http_gzip_module、 IIS では <httpCompression> 要素があります。

ホップバイホップの圧縮

ホップバイホップの圧縮はエンドツーエンドの圧縮に似ています。しかし、サーバー内のリソースでは圧縮を行わずに特定の表現形式を生成して転送しますが、クライアントとサーバーの間のパス上にある任意の 2 つのノードの間でメッセージの本体が圧縮されるという根本的な違いがあります。連続した中間ノードの間のコネクションで、異なる圧縮が行われることがあります。

非圧縮 HTTP 本体をネットワークノード経由でクライアントに送信するサーバー。本体はクライアントに到達する前に、'Transfer-Encoding' ヘッダーによってネットワーク上のノードで圧縮・展開されます。

これを行うために、 HTTP ではエンドツーエンドの圧縮のコンテンツネゴシエーションに似ている仕組みを使用します。リクエストを転送するノードは TE (en-US) ヘッダーを使用して圧縮アルゴリズムを伝えます。相手のノードは適切な方式を選択して圧縮を行い、 Transfer-Encoding ヘッダーを使用して、選択した方式を示します。

クライアントが、圧縮関連のヘッダーを持たないコンテンツをサーバーにリクエストされた場合。サーバーは圧縮されていない本体で応答します。本体がクライアントにリーチするまでに、ネットワーク上のノードで圧縮と展開が行われます。

実際は、ホップバイホップの圧縮はサーバーやクライアントにとって透過的であり、あまり使用されません。 TE (en-US) および Transfer-Encoding は主にチャンク形式でレスポンスを送信するために使用され、長さがわからないリソースの転送を開始することができます。

ホップレベルで圧縮や Transfer-Encoding を使用することは Apache、Nginx、IIS などほとんどのサーバーでまれであり、簡単に設定する方法はありません。このような設定は、主にプロキシーレベルで行います。