不要なリソースのダウンロードを排除する以外に、ページの読み込み速度を改善するためにできる最善の方法は、残りのリソースを最適化して圧縮し、全体的なダウンロード サイズを最小限に抑えることです。
データ圧縮の基本
未使用のリソースをダウンロードしないようにウェブサイトを設定したら、次は、ブラウザがダウンロードする必要がある残りの対象リソースを圧縮します。リソースの種類(テキスト、画像、フォントなど)に応じて、さまざまな手法を選択できます。たとえば、ウェブサーバーで有効にできる汎用ツール、特定のコンテンツ タイプに対する前処理の最適化、デベロッパーからの入力を必要とするリソース固有の最適化などがあります。
最高のパフォーマンスを実現するには、次のすべての手法を組み合わせる必要があります。
- 圧縮とは、より少ないビット数で情報をエンコードするプロセスです。
- 不要なデータを除外すると、常に最良の結果が得られます。
- 圧縮技術やアルゴリズムにはさまざまな種類があります。
- 最適な圧縮を実現するには、さまざまな手法が必要になります。
データのサイズを縮小するプロセスは、データ圧縮です。多くの人々が、圧縮率、圧縮速度、さまざまな圧縮アルゴリズムに必要なメモリを改善するために、アルゴリズム、手法、最適化に貢献してきました。
データ圧縮の詳細な説明は、このガイドの範囲外です。ただし、圧縮の仕組みと、ページに必要なさまざまなアセットのサイズを縮小するために使用できる手法を大まかに理解しておくことが重要です。
これらの手法の基本原則を説明するために、この例のために考案されたシンプルなテキスト メッセージ形式を最適化するプロセスについて考えてみましょう。
# 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% |
上の表は、いくつかのよく知られた JavaScript ライブラリで Brotli 圧縮と gzip 圧縮の両方を使用した場合の削減量を示しています。ファイルとアルゴリズムに応じて、65% から 86% の削減が可能です。参考までに、Brotli と gzip の両方で、各ファイルに最大圧縮レベルが適用されました。可能であれば、gzip よりも Brotli を優先します。
圧縮を有効にすることは、最もシンプルで効果的な最適化方法の一つです。ウェブサイトでこの機能を活用していない場合は、ユーザーのパフォーマンスを向上させる大きな機会を逃していることになります。幸いなことに、多くのウェブサーバーには、この重要な最適化を可能にするデフォルト構成が用意されています。特に CDN は、圧縮速度と圧縮率のバランスを取る方法で実装するのに非常に効果的です。
圧縮が機能していることを確認する簡単な方法は、Chrome DevTools を開き、[Network] パネルを開いて、任意のページを読み込み、ネットワーク パネルの一番下を確認することです。
上の画像のように、次の内訳が表示されます。
- リクエストの数。これは、ページに読み込まれたリソースの数です。
- すべてのリクエストの転送サイズ。これは、ページのいずれかのリソースに適用された圧縮の効果を反映しています。
- すべてのリクエストのリソースサイズ。これは、解凍後のページのリソースの大きさを示しています。
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 はリソースを圧縮できるだけでなく、非常に高速に圧縮できます。
これらのベースライン パフォーマンスのコンセプトをウェブサイトのアーキテクチャに組み込むことで、パフォーマンス最適化の取り組みを適切な基盤に据え、その後の最適化を適切なベースライン プラクティスの強固な基盤に据えることができます。