不要なリソースのダウンロードの回避に続く、ページの読み込み速度を向上するために可能な最良の対策は、残りのリソースの最適化と圧縮によって合計ダウンロード サイズを最小限に抑えることです。
データ圧縮の概要
不要なリソースをすべて取り除いたら、次の手順はブラウザがダウンロードする必要がある残りのリソースの合計サイズを最小限に抑える、つまり圧縮することです。 リソースの種類(テキスト、画像、フォントなど)に応じて、サーバーで有効にできる汎用ツール、コンテンツの特定の種類向けの前処理最適化、デベロッパーの入力を必要とするリソース別の最適化など、自由に利用できるさまざまな技法があります。
パフォーマンスを最適化するには、このすべての技法を組み合わせる必要があります。
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.
format: secret-cipher
date:08/25/16
AAAZZBBBBEEEMMM EEETTTAAA
- メッセージには任意の注釈が含まれていることがあり、注釈であることは接頭辞「#」で分かります。 注釈はメッセージの意味やその他の振る舞いに一切影響しません。
- メッセージには、ヘッダーが含まれていることがあります。これは「:」で区切られたキーと値のペアであり、メッセージの先頭にある必要があります。
- メッセージはテキストのペイロードを伝送します。
現時点で長さが 200 文字ある上記のメッセージのサイズを小さくするにはどうすればよいでしょうか。
- コメントは興味深いですが、メッセージの意味に影響しないので、 メッセージを送信する際に取り除きます。
- ヘッダーを効率的にエンコードするために使用できる高度な技法があります。 たとえば、すべてのメッセージに必ず「format」と「date」があると分かっている場合、短い整数 ID に変換しその ID を送信することができます。 ただ、必ずあるかどうか分からないので、とりあえずヘッダーはそのまま残しておきます。
- ペイロードはテキストのみです。テキストのコンテンツが実際に何かはわかりませんが(「秘密のメッセージ」を使用していることは明らかですが)、テキストを見ると、かなり冗長性があるようです。 文字の繰り返しを送信するのではなく、繰り返されている文字の数を数えれば、もっと効率的にエンコードできるのではないでしょうか。 たとえば、「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 を適用すると効果が高いことがわかります。
- 最初にコンテンツ別の最適化(CSS、JS、HTML の縮小化ツール)を適用します。
- GZIP を適用して縮小後の出力を圧縮します。
GZIP の有効化は、最も実装が簡単で効果がある最適化手法の 1 つです。しかし、残念ながら多くの人が GZIP を実行していません。 大半のウェブサーバーはコンテンツを圧縮してくれるため、あとは GZIP 圧縮の効果があるすべての種類のコンテンツを圧縮するようにサーバーが正しく設定されていることを確認するだけです。
HTML5 Boilerplate プロジェクトには、人気の高いすべてのサーバー向けのサンプル構成ファイルが用意されており、構成フラグと設定ごとに詳細なコメントが記載されています。 サーバーにとって最適な設定を判断するには、次の手順を実行します。
- リストでお気に入りのサーバーを見つけます。
- GZIP のセクションを探します。
- サーバーが推奨されている設定になっていることを確認します。
GZIP の動作は、Chrome DevTools を起動して [Network] パネルの [Size / Content] 列を調べれば簡単に確認できます。 「Size」はアセットの転送サイズを示し、「Content」はアセットの未圧縮サイズを示しています。 上記の例の HTML アセットでは、GZIP により転送時に 98.8 KB 削減されます。
注: GZIP を使用するとアセットのサイズが大きくなる可能性もあります。 通常、これが発生するのは、アセットが非常に小さく、GZIP ディクショナリのオーバーヘッドが圧縮による削減よりも大きくなる場合や、リソースが既に十分に圧縮されている場合です。 この問題を回避するため、一部のサーバーでは「ファイルサイズの下限しきい値」を指定できます。
最後に、ほとんどのサーバーはユーザーにアセットを提供する際にそのアセットを自動的に圧縮しますが、一部の CDN では、確実に GZIP アセットを提供するために、細心の注意と手動設定が必要になります。 サイトを監査し、アセットが実際に圧縮されていることを確認してください。