ページの読み込み速度を改善するうえで、不要なリソースのダウンロードを排除する次に効果的なのは、残りのリソースを最適化して圧縮し、ダウンロード サイズ全体を最小限に抑えることです。
データ圧縮入門ガイド
未使用のリソースをダウンロードしないようにウェブサイトを設定したら、次のステップとして、ブラウザがダウンロードする必要がある残りの対象リソースを圧縮します。リソースの種類(テキスト、画像、フォントなど)に応じて、ウェブサーバーで有効にできる汎用ツール、特定のコンテンツ タイプに対する事前処理の最適化、デベロッパーの入力が必要なリソース固有の最適化など、さまざまな手法を選択できます。
最高のパフォーマンスを実現するには、次のすべての手法を組み合わせる必要があります。
- 圧縮とは、より少ないビット数で情報をエンコードするプロセスです。
- 不要なデータを削除すると、常に最良の結果が得られます。
- 圧縮手法とアルゴリズムは多種多様です。
- 最適な圧縮を実現するには、さまざまな手法が必要です。
データのサイズを縮小するプロセスは、データ圧縮と呼ばれます。多くの人が、さまざまな圧縮アルゴリズムの圧縮率、圧縮速度、必要なメモリを改善するためのアルゴリズム、手法、最適化に貢献してきました。
データ圧縮の詳細な説明は、このガイドの範囲外です。ただし、圧縮の仕組みと、ページで必要となるさまざまなアセットのサイズを縮小するために使用できる手法を大まかに理解しておくことは重要です。
これらの手法の基本原則を説明するために、この例のために考案されたシンプルなテキスト メッセージ形式を最適化するプロセスについて考えてみましょう。
# 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
- メッセージには、任意のアノテーション(コメントと呼ばれることもあります)を含めることができます。アノテーションは「#」接頭辞で示されます。アノテーションは、メッセージの意味や動作に影響しません。
- メッセージには、メッセージの先頭に表示される Key-Value ペア(上記の例では
":"で区切られています)であるヘッダーが含まれている場合があります。 - メッセージはテキスト ペイロードを伝送します。
200 文字から始まる前のメッセージのサイズを小さくするにはどうすればよいですか?
- コメントは興味深いものですが、メッセージの意味には影響しません。メッセージを送信する際に削除します。
- ヘッダーを効率的にエンコードする優れた手法があります。たとえば、すべてのメッセージに「format」と「date」が含まれていることがわかっている場合は、それらを短い整数 ID に変換して送信するだけで済みます。ただし、そうでない可能性もあるため、今のところはそのままにしておくことをおすすめします。
- ペイロードはテキストのみです。(どうやら
"secret-cipher"を使用しているようですが)その内容が実際にはどうなっているのかはわかりませんが、テキストを見るだけでも、冗長な部分が多いことがわかります。たとえば、同じ文字を繰り返して送信する代わりに、繰り返された文字の数を数えて、より効率的にエンコードできます。たとえば、"AAA"は"3A"になります。これは、3 つの A のシーケンスを表します。
これらの手法を組み合わせると、次の結果が得られます。
format: secret-cipher
date: 08/25/16
3A2Z4B3E3M 3E3T3A
新しいメッセージの長さは 56 文字です。つまり、元のメッセージを 72% 圧縮したことになります。大幅な削減ですね。
これは、圧縮アルゴリズムがテキストベースのリソースの転送サイズを削減するのにどのように役立つかを示す簡単な例です。実際には、圧縮アルゴリズムは上記の例よりもはるかに複雑です。ウェブでは、圧縮アルゴリズムを使用して、リソースのダウンロード時間を大幅に短縮できます。テキストベースのアセットに圧縮を適用すると、ウェブページがリソースの読み込みに費やす時間を短縮できるため、ユーザーは圧縮なしの場合よりも早くリソースの効果を確認できます。
軽量化: 前処理とコンテキスト固有の最適化
ここで説明する最初の手法は、最小化です。最小化は厳密には圧縮アルゴリズムではありませんが、ソースコードで使用されている不要な文字や冗長な文字を削除して、リソースを人間が読みやすくする方法です。ただし、本番環境のウェブサイトでソースコードの機能を維持するために、その可読性は必要ありません。また、ウェブ上のリソースの読み込みが遅れる可能性があります。
最小化は、配信されるリソースのサイズを大幅に削減できるコンテンツ固有の最適化の一種です。この最適化は、ビルドとデプロイのプロセスの一部として適用するのが最適です。たとえば、バンドラーは、新しい本番環境コードをウェブサイトにデプロイする直前にリソースを自動的に最小化できる、一般的に使用されるソフトウェアの一種です。
冗長なデータや不要なデータを圧縮する最善の方法は、それらを削除することです。ただし、任意のデータを削除することはできません。ただし、データ形式とそのプロパティに関するコンテンツ固有の知識があるコンテキストでは、実際の意味や機能を損なうことなく、ペイロードのサイズを大幅に削減できます。
<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>
This is my awesome container, and it is <em>so</em> awesome.
</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 つに折りたたんで、より多くのバイトを節約できます。CSS ルールが多数ある場合は、このような冗長性を削除すると効果がありますが、セレクタはメディアクエリ内など、異なるコンテキストで重複することが多いため、積極的に適用できるとは限りません。 - スペースとタブは、HTML、CSS、JavaScript における開発者の便宜です。追加のコンプレッサーは、すべてのタブとスペースを削除する可能性があります。他の重複排除手法とは異なり、この種の最適化は、ページを表示するうえでスペースやタブが不要である限り、かなり積極的に適用できます。たとえば、HTML ドキュメント内のテキストの実行におけるスペースは、ユーザーが実際に目にするコンテンツの読みやすさを確保するため、保持する必要があります。
<html><head><style>.awesome-container{font-size:120%;width:50%}</style></head><body><div>This is my awesome container, and it is <em>so</em> awesome.</div><script>awesomeAnalytics()</script></body></html>
前述の手順を適用すると、ページは 516 文字から 204 文字に減少し、約 60% の削減になります。確かに、読みやすいとは言えませんが、使用可能にするために順序付けする必要はありません。最新の開発プラクティスでは、ソースコードの読みやすい形式のバージョンを、本番環境にリリースする最適化されたコードとは別に保持することもできます。ソースマップ(変換された本番環境コードを読み取り可能な形式で表現し、本番環境でのバグのトラブルシューティングを容易にする)と組み合わせることで、ユーザー エクスペリエンスのためにパフォーマンスを最適化しながら、優れたデベロッパー エクスペリエンスを実現できます。
前の例は、重要なポイントを示しています。汎用コンプレッサ(任意のテキストを圧縮するように設計されたものなど)は、前の例のページをかなりうまく圧縮できますが、コメントの削除、CSS ルールの折りたたみ、その他数十ものコンテンツ固有の最適化を行うことはできません。そのため、プリプロセス、最小化、その他のコンテキスト認識型最適化が重要になります。
同様に、上記の手法はテキストベースのアセットだけでなく、他のアセットにも拡張できます。画像、動画、その他のコンテンツ タイプには、それぞれ独自の形式のメタデータとさまざまなペイロードが含まれています。たとえば、カメラで写真を撮ると、通常、そのファイルにはカメラの設定や位置情報など、多くの追加情報が埋め込まれます。アプリケーションによっては、このデータが重要になることもあれば(写真共有サイトなど)、まったく役に立たないこともあります。削除する価値があるかどうかを検討する必要があります。実際には、このメタデータは画像ごとに数十キロバイトになることがあります。
つまり、アセットの効率を最適化する最初のステップとして、さまざまなコンテンツ タイプのインベントリを作成し、サイズを縮小するために適用できるコンテンツ固有の最適化の種類を検討します。次に、それらの最適化を特定したら、ビルドとリリースの手順に追加して自動化し、新しいリリースが本番環境にリリースされるたびに、最適化が常に適用されるようにします。
圧縮アルゴリズムによるテキスト圧縮
テキストベースのアセットのサイズを縮小する次のステップは、圧縮アルゴリズムを適用することです。この方法は、テキストベースのペイロードをユーザーに送信する前に、繰り返し可能なパターンを積極的に検索し、ユーザーのブラウザに届いたときに解凍することで、さらに一歩進んでいます。その結果、これらのリソースが大幅に削減され、ダウンロード時間が短縮されます。
- gzip と Brotli は、テキストベースのアセット(CSS、JavaScript、HTML)で最適なパフォーマンスを発揮する、一般的に使用されている圧縮アルゴリズムです。
- 最新のブラウザはすべて gzip と Brotli の圧縮をサポートしており、
Accept-EncodingHTTP リクエスト ヘッダーで両方のサポートをアドバタイズします。 - 圧縮を有効にするようにサーバーを構成する必要があります。ウェブサーバー ソフトウェアでは、テキストベースのリソースを圧縮するモジュールがデフォルトで有効になっていることがよくあります。
- gzip と Brotli の両方で、圧縮レベルを調整して圧縮率を向上させることができます。gzip の場合、圧縮設定の範囲は 1 ~ 9 で、9 が最適です。Brotli の場合、この範囲は 0 ~ 11 で、11 が最適です。ただし、圧縮率が高いほど時間がかかります。動的に圧縮されるリソース(リクエスト時)の場合、範囲の中間の設定では、圧縮率と速度のバランスが最も優れている傾向があります。ただし、静的圧縮は可能です。これは、レスポンスが事前に圧縮されるため、各圧縮アルゴリズムで使用可能な最もアグレッシブな圧縮設定を使用できる場合です。
- コンテンツ配信ネットワーク(CDN)では、通常、対象となるリソースの自動圧縮が提供されています。CDN は動的圧縮と静的圧縮も管理できるため、圧縮について心配する必要がなくなります。
gzip と Brotli は、任意のバイトストリームに適用できる一般的なコンプレッサです。内部的には、ファイルで以前に調べたコンテンツの一部を記憶し、重複するデータ フラグメントを効率的に検索して置き換えようとします。
実際には、gzip と Brotli の両方ともテキストベースのコンテンツで最高のパフォーマンスを発揮し、大きなファイルでは 70 ~ 90% の圧縮率を達成することがよくあります。ただし、代替アルゴリズム(可逆圧縮または非可逆圧縮の手法を使用するほとんどの画像形式など)を使用してすでに圧縮されているアルゴリズム アセットを実行しても、ほとんど改善されません。
最新のブラウザはすべて、Accept-Encoding HTTP リクエスト ヘッダーで gzip と Brotli のサポートをアドバタイズしています。ただし、クライアントがリクエストしたときに圧縮されたリソースを提供するようにウェブサーバーが正しく構成されていることを確認するのは、ホスティング プロバイダの責任です。
| ファイル | アルゴリズム | 非圧縮サイズ | 圧縮後のサイズ | 圧縮比 |
|---|---|---|---|---|
| angular-1.8.3.js | Brotli | 1,346 KiB | 256 KiB | 81% |
| angular-1.8.3.js | gzip | 1,346 KiB | 329 KiB | 76% |
| angular-1.8.3.min.js | Brotli | 173 KiB | 53 KiB | 69% |
| angular-1.8.3.min.js | gzip | 173 KiB | 60 KiB | 65% |
| jquery-3.7.1.js | Brotli | 302 KiB | 69 KiB | 77% |
| jquery-3.7.1.js | gzip | 302 KiB | 83 KiB | 73% |
| jquery-3.7.1.min.js | Brotli | 85 KiB | 27 KiB | 68% |
| jquery-3.7.1.min.js | gzip | 85 KiB | 30 KiB | 65% |
| lodash-4.17.21.js | Brotli | 531 KiB | 73 KiB | 86% |
| lodash-4.17.21.js | gzip | 531 KiB | 94 KiB | 82% |
| lodash-4.17.21.min.js | Brotli | 71 KiB | 23 KiB | 68% |
| lodash-4.17.21.min.js | gzip | 71 KiB | 25 KiB | 65% |
上の表は、Brotli 圧縮と gzip 圧縮の両方で、いくつかの有名な JavaScript ライブラリで実現できる節約量を示しています。削減率は、ファイルとアルゴリズムに応じて 65% ~ 86% の範囲になります。参考までに、Brotli と gzip の両方で、各ファイルに最大圧縮レベルが適用されました。可能な限り、gzip よりも Brotli を優先します。
圧縮を有効にすることは、実装する最もシンプルで効果的な最適化の 1 つです。ウェブサイトでこの機能を利用していない場合、ユーザーのパフォーマンスを改善する大きな機会を逃していることになります。幸いなことに、多くのウェブサーバーにはこの重要な最適化を可能にするデフォルト構成が用意されています。特に CDN は、圧縮速度と圧縮率のバランスを取りながらこの最適化を実装するのに非常に効果的です。
圧縮の動作を確認する簡単な方法は、Chrome DevTools を開き、[ネットワーク] パネルを開き、任意のページを読み込んで、ネットワーク パネルの一番下を確認することです。
上の画像のように、次の内訳が表示されます。
- リクエストの数。これは、ページに読み込まれたリソースの数です。
- すべてのリクエストの転送サイズ。これは、ページのいずれかのリソースに適用された圧縮の有効性を反映しています。
- すべてのリクエストのリソース サイズ。これは、ページのリソースが解凍された後のサイズを反映しています。
Core Web Vitals への影響
パフォーマンスの改善を反映する指標がないと、パフォーマンスの改善を測定できません。Core Web Vitals の取り組みは、実際のユーザー エクスペリエンスを反映する指標を作成し、その認知度を高めるために存在します。これは、単純なページの読み込み時間など、ユーザー エクスペリエンスの質に明確に反映されない指標とは対照的です。
このガイドで説明する最適化をウェブサイトのリソースに適用すると、最適化されたリソースと関連する指標に応じて、Core Web Vitals への影響が異なる場合があります。ただし、これらの最適化を適用することで、ウェブサイトの Core Web Vitals を改善できる場合があります。
- 最小化および圧縮された HTML リソースは、その HTML の読み込み、サブリソースの検出可能性を改善し、それらの読み込みを改善します。これは、ページの Largest Contentful Paint(LCP)にメリットをもたらす可能性があります。
rel="preload"などのリソース ヒントを使用してリソースの検出可能性に影響を与えることができますが、リソース ヒントを過度に使用すると、帯域幅の競合に関する問題が発生する可能性があります。ナビゲーション リクエストの HTML レスポンスを圧縮することで、その中のリソースを プリロード スキャナでできるだけ早く検出できます。 - 圧縮を使用すると、一部の LCP 候補をより早く読み込むこともできます。たとえば、LCP 候補である SVG 画像は、テキストベースの圧縮によってリソース読み込み時間を短縮できます。これは、JPEG 画像が不可逆圧縮を使用するなど、他の圧縮方法で本質的に圧縮される他の画像タイプに対して行う最適化とは異なります。
- また、テキストノードは LCP 候補にもなります。このガイドで説明する手法は、ウェブページのテキストにウェブフォントを使用しているかどうかによって異なります。ウェブフォントを使用している場合は、ウェブフォントの最適化に関するベスト プラクティスが適用されます。ただし、ウェブフォントではなく、リソース読み込み時間を発生させずに表示されるシステム フォントを使用している場合は、CSS を縮小して圧縮することでこの時間を短縮できます。つまり、LCP テキスト ノードのレンダリングをより早く行うことができます。
まとめ
テキストベースのアセットのエンコードと転送を最適化する方法は、パフォーマンスの基本的なコンセプトですが、大きな影響があります。縮小と圧縮の対象となるリソースがこれらの最適化のメリットを確実に享受できるように、できる限りの対策を講じていることを確認してください。
さらに重要なのは、これらのプロセスが自動化されていることを確認することです。縮小化には、バンドラを使用して、対象となるリソースに縮小化を適用します。ウェブサーバーの設定で圧縮がサポートされていることを確認し、さらに、利用可能な最も効果的な圧縮を使用します。これをできるだけ簡単にするには、CDN を使用して圧縮を自動化します。CDN はリソースを圧縮できるだけでなく、非常に高速に圧縮できます。
これらのベースライン パフォーマンスのコンセプトをウェブサイトのアーキテクチャに組み込むことで、パフォーマンスの最適化の取り組みが順調に進み、その後の最適化が優れたベースライン プラクティスの確固たる基盤の上に構築されるようになります。