テキストベースのアセットのエンコードと転送サイズの最適化

不要なリソースのダウンロードの回避に続く、ページの読み込み速度を向上するために可能な最良の対策は、残りのリソースの最適化と圧縮によって合計ダウンロード サイズを最小限に抑えることです。

データ圧縮の概要

不要なリソースをすべて取り除いたら、次の手順はブラウザがダウンロードする必要がある残りのリソースの合計サイズを最小限に抑える、つまり圧縮することです。リソースの種類(テキスト、画像、フォントなど)に応じて、サーバーで有効な汎用ツール、コンテンツの種類別の前処理最適化、デベロッパーの入力を必要とするリソース別の最適化など、自由に利用できるさまざまな技術があります。

パフォーマンスを最適化するには、このすべての技術を組み合わせる必要があります。

TL;DR

  • 圧縮とは、ビット数を削減して情報をエンコードする処理です。
  • 不要なデータの除去は必ず最良の結果に結び付きます。
  • さまざまな圧縮技術と圧縮アルゴリズムがあります。
  • 最適な圧縮を実現するにはさまざまな技術が必要になります。

データサイズを縮小する処理のことをデータ圧縮と呼びます。多くの人がアルゴリズム、技術、最適化に取り組み、圧縮率、圧縮速度、各種圧縮に必要なメモリ容量を向上させてきました。もちろん、このテーマをすべて説明することがここでの目的ではありませんが、重要なのは、圧縮の仕組みと、ページに必要な各種アセットのサイズを縮小するために利用できる技術の概要を理解することです。

こうした技術の基本方針を説明するために、特別に作成した単純なテキスト メッセージ形式を最適化するにはどうすればよいかを検討してみましょう。

# Below is a secret message, which consists of a set of headers in
# key-value format followed by a newline and the encrypted message.

08/25/16
AAAZZBBBBEEEMMM EEETTTAAA
  1. メッセージには任意の注釈が含まれていることがあり、接頭辞「#」で示されています。注釈はメッセージの意味やその他の振る舞いに一切影響しません。
  2. メッセージには、ヘッダーが含まれていることがあります。これは「:」で区切られた key-value ペアであり、メッセージの先頭にある必要があります。
  3. メッセージはテキストのペイロードを伝送します。

現時点で長さが 200 文字ある上記のメッセージのサイズを削減するにはどうすればよいでしょうか。

  1. コメントは興味深いですが、メッセージの意味に影響しないことがわかっているので、メッセージを送信する際に取り除きます。
  2. ヘッダーを効率的にエンコードするために使用できる高度な技術があります。たとえば、すべてのメッセージに必ず「format」と「date」があるかどうかはわかりませんが、これらがあれば、短い整数 ID に変換しその ID を送信することができます。ただ、このケースに当てはまるかどうかわからないので、とりあえずヘッダーはそのまま残しておきます。
  3. ペイロードはテキストのみです。テキストのコンテンツが実際に何かはわかりませんが(「秘密のメッセージ」を使用していることは明らかですが)、テキストを見ると、かなり冗長性があるようです。文字の繰り返しを送信するのではなく、繰り返されている文字の数を数えれば、もっと効率的にエンコードできるのではないでしょうか。たとえば、「AAA」は「3A」になります。A が 3 つ連続しているという意味です。

この技術を組み合わせると、次のような結果になります。

format: secret-cipher
date: 08/25/16
3A2Z4B3E3M 3E3T3A

新しいメッセージの長さは 56 文字です。つまり、元のメッセージを 72% も圧縮できたことになります。

良い結果が得られましたが、このことがウェブページの最適化にどう役立つのでしょうか。圧縮アルゴリズムを発明するわけではありませんが、おわかりのように、最適化するページ上のリソースは変わっても、前処理、コンテキスト別の最適化、コンテンツ別のアルゴリズムなど、使用する技術と考え方はまったく同じです。

縮小化: 前処理とコンテキスト固有の最適化

TL;DR

  • コンテンツ固有の最適化により、配信されるリソースのサイズを大幅に削減できます。
  • コンテンツ固有の最適化はビルド / リリース サイクルの一部として適用することが推奨されます。

冗長なデータや不要なデータを圧縮する最も良い方法は、まるごと削除することです。データをむやみに削除することはできませんが、データ形式とそのプロパティについてコンテンツ固有の知識があれば、実際の意味に影響を与えることなくペイロードのサイズを大幅に削減できることが多くあります。

<html>
  <head>
  <style>
     /* awesome-container is only used on the landing page */
     .awesome-container { font-size: 120% }
     .awesome-container { width: 50% }
  </style>
 </head>

 <body>
   <!-- awesome container content: START -->
    <div>…</div>
   <!-- awesome container content: END -->
   <script>
     awesomeAnalytics(); // beacon conversion metrics
   </script>
 </body>
</html>

サンプルを見る

上記のシンプルな HTML ページと、このページに含まれている 3 つの異なるコンテンツの種類(HTML マークアップ、CSS スタイル、JavaScript)を考えてみましょう。コンテンツの種類ごとに、有効なコンテンツを構成するルールや、コメントを示すためのルールなどが異なります。では、このページのサイズを縮小するにはどうすればよいでしょうか。

  • コードのコメントはデベロッパーにとっては重要ですが、ブラウザで表示する必要はありません。CSS(/* … */)、HTML(<!-- … -->)、JavaScript(// …)のコメントを除去するだけで、ページの合計サイズを大幅に削減できます。
  • 「高性能」な CSS 圧縮ツールであれば、「.awesome-container」のルールが効率的に定義されていないことを認識して、他のスタイルに影響を与えずに 2 つの宣言を 1 つにできるため、バイト数はさらに削減されます。
  • 空白(スペースとタブ)は、デベロッパーの便宜のために HTML、CSS、JavaScript に含まれています。圧縮ツールを追加して、タブとスペースをすべて削除する対応も考えられます。
<html><head><style>.awesome-container{font-size:120%;width: 50%}
</style></head><body><div>…</div><script>awesomeAnalytics();
</script></body></html>

サンプルを見る

上記の手順を適用すれば、このページは 406 文字から 150 文字になります。圧縮による削減率は 63% になります。確かにあまり読みやすくはありませんが、読みやすくする必要もありません。元のページは「開発バージョン」として保存しておき、ページをウェブサイトに公開する準備ができたら必ず上述の手順を適用します。

一歩離れてみると、上記の例から重要な点がわかります。汎用の圧縮ツール、たとえば任意のテキストを圧縮するように作られたツールで、上記のページをかなり効率よく圧縮できるかもしれませんが、コメントの削除や CSS ルールの縮小化など、コンテンツ固有の数十種類にのぼる最適化は取り入れていません。このため、前処理、縮小化、コンテキストに対応した最適化が強力なツールになる可能性があります。

注: JQuery ライブラリが良い例で、圧縮前の開発バージョンは 300 KB に達しようとしています。同じライブラリでも縮小化(コメントの削除などを実施)したものは約 1/3 の大きさで、100 KB 程度です。

同様に、上記の技術は単なるテキストベースのアセット以外にも応用できます。画像、動画、その他の種類のコンテンツには、いずれも独自の形式のメタデータやさまざまなペイロードが含まれています。たとえば、カメラで写真を取るたびに、通常、写真にはカメラの設定、場所など多くの追加情報が埋め込まれています。アプリケーションによっては、このデータが重要になることもあれば(写真共有サイトなど)、まったく無意味なこともあるため、削除することが妥当かどうかを検討する必要があります。実際、このメタデータは、1 画像あたり合計数十キロバイトに及ぶことがあります。

まとめると、アセットの効率性を最適化する最初の手順は、さまざまなコンテンツの種類の一覧表を作成し、どのようなコンテンツ固有の最適化を適用すればサイズを縮小できるかを検討することです。何が最適化になるかを判断したら、次に、その最適化をビルドとリリースのプロセスに追加して自動化します。これが、最適化を確実に実施できる唯一の方法です。

GZIP によるテキストの圧縮

TL;DR

  • GZIP はテキストベースのアセット(CSS、JavaScript、HTML)で最大限の効果を発揮します。
  • 最新のブラウザはすべて GZIP 圧縮に対応しており、自動的にこの圧縮をリクエストします。
  • サーバーを GZIP 圧縮に対応するように設定する必要があります。
  • 一部の CDN は GZIP が有効化されていることを確認するために特に注意が必要です。

GZIP はどのようなバイトストリームにも適用できる汎用の圧縮ツールです。GZIP の内部では以前表示されたコンテンツの一部を記憶し、重複するデータ フラグメントを効率よく検索して置換することを試みます(関心があれば、詳しい GZIP の説明をご確認ください)。実際、GZIP で最適なパフォーマンスが得られるのはテキストベースのコンテンツであり、大きいファイルの場合、圧縮率は 70~90% にもなります。一方、別のアルゴリズムで既に圧縮されているアセット(大部分の画像形式など)に GZIP を実行しても、ほとんどまたはまったく効果がありません。

最新のブラウザはすべて GZIP 圧縮に対応しており、すべての HTTP リクエストで GZIP 圧縮のネゴシエーションが自動的に実施されます。ここで必要なことは、クライアントからリクエストされたときに圧縮後のリソースを提供するようにサーバーが正しく設定されていることを確認することです。

ライブラリ サイズ 圧縮後のサイズ 削減率
jquery-1.11.0.js 276 KB 82 KB 70%
jquery-1.11.0.min.js 94 KB 33 KB 65%
angular-1.2.15.js 729 KB 182 KB 75%
angular-1.2.15.min.js 101 KB 37 KB 63%
bootstrap-3.1.1.css 118 KB 18 KB 85%
bootstrap-3.1.1.min.css 98 KB 17 KB 83%
foundation-5.css 186 KB 22 KB 88%
foundation-5.min.css 146 KB 18 KB 88%

上記の表は、一般的な JavaScript ライブラリと CSS フレームワークに GZIP を適用した場合の削減率を示したものです。削減率は 60~88% です。縮小化されたファイル(ファイル名に「.min」があるファイル)に GZIP を適用すると効果が高いことがわかります。

  1. 最初にコンテンツ別の最適化(CSS、JS、HTML の縮小化ツール)を適用します。
  2. GZIP を適用して縮小化後の出力を圧縮します。

GZIP の有効化は、最も実装が簡単で効果がある最適化手法の 1 つです。しかし、残念ながら多くの人が GZIP を実行していません。大半のウェブサーバーでは自動的にコンテンツを圧縮するため、あとは GZIP 圧縮の効果があるすべての種類のコンテンツを圧縮するようにサーバーが正しく設定されていることを確認するだけです。

HTML5 Boilerplate プロジェクトには、人気の高いすべてのサーバー向けのサンプル構成ファイルが用意されており、構成フラグと設定ごとに詳細なコメントが記載されています。サーバーにとって最適な設定を判断するには、次の手順を実行します。 リストでお気に入りのサーバーを見つけます。 GZIP のセクションで探します。 * 推奨されている設定でサーバーが設定されていることを確認します。

実際のサイズと転送サイズの DevTools デモ

GZIP の動作は、Chrome DevTools を起動して [Network] パネルの [Size / Content] 列を調べれば簡単に確認できます。「Size」はアセットの転送サイズを示し、「Content」はアセットの未圧縮サイズを示しています。上記の例の HTML アセットでは、GZIP により転送時に 98.8 KB 削減されます。

注: GZIP を使用するとアセットのサイズが拡大する可能性もあります。通常、これが発生するのは、アセットが非常に小さく、GZIP ディクショナリのオーバーヘッドが圧縮による削減よりも高くなる場合や、リソースが既に十分に圧縮されている場合です。一部のサーバーでは、「ファイルサイズの下限しきい値」を指定してこの問題を回避できます。

最後に、ほとんどのサーバーはユーザーにアセットを提供する際にそのアセットを自動的に圧縮しますが、一部の CDN では、確実に GZIP アセットを提供するために、細心の注意と手動設定が必要になります。サイトを監査し、アセットが実際に圧縮されていることを確認してください。