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

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

未使用のリソースのダウンロードを回避するようにウェブサイトを設定したら、次のステップは、ブラウザがダウンロードする必要がある残りの対象リソースを圧縮することです。リソースの種類(テキスト、画像、フォントなど)に応じて、ウェブサーバーで有効にできる汎用ツール、コンテンツの種類別の前処理最適化、デベロッパーの入力を必要とするリソース別の最適化など、自由に利用できるさまざまな技術があります。

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

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

データサイズを縮小する処理のことをデータ圧縮と呼びます。多くの人がアルゴリズム、技術、最適化に取り組み、圧縮率、圧縮速度、各種圧縮アルゴリズムによって必要なメモリ容量を向上させてきました。

データ圧縮の詳細については、このガイドの範囲を超えています。重要なのは、圧縮の仕組みと、ページに必要な各種アセットのサイズを縮小するために利用できる技術の概要を理解することです。

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

# 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
  1. メッセージには任意の注釈(コメント)が含まれていることがあり、接頭辞「#」で示されています。注釈はメッセージの意味や動作に影響しません。
  2. メッセージにはヘッダーが含まれていることがあります。これは、メッセージの先頭に表示される Key-Value ペア(上記の例では ":" で区切られています)です。
  3. メッセージはテキストのペイロードを伝送します。

200 文字から始まる上記のメッセージのサイズを小さくするにはどうすればよいでしょうか。

  1. コメントは興味深いですが、メッセージの意味に影響しないので、メッセージを送信する際に取り除きます。
  2. ヘッダーを効率的にエンコードするために使用できる高度な技術があります。たとえば、すべてのメッセージに必ず「format」と「date」があると分かっている場合、短い整数 ID に変換しその ID を送信することができます。ただし、必ずあるかどうか分からないので、とりあえずヘッダーはそのまま残しておきます。
  3. ペイロードはテキストのみです。テキストのコンテンツが実際に何であるかはわかりませんが("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 つの異なるコンテンツの種類について考えてみましょう。

  1. HTML マークアップ。
  2. ページの表示をカスタマイズするための CSS。
  3. 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 ルールの圧縮、その他のコンテンツ固有の最適化を実行することはできません。そのため、前処理、縮小化、その他のコンテキスト対応の最適化が重要になります。

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

まとめると、アセットの効率性を最適化する最初の手順は、さまざまなコンテンツの種類の一覧表を作成し、どのようなコンテンツ固有の最適化を適用すればサイズを縮小できるかを検討することです。最適化方法を特定したら、次に、その最適化処理をビルドとリリースのプロセスに取り入れて自動化します。こうして、本番環境への新しいリリースごとに最適化が確実に適用されるようにします。

圧縮アルゴリズムによるテキスト圧縮

テキストベースのアセットのサイズを削減する次のステップは、圧縮アルゴリズムを適用することです。さらに、テキストベースのペイロードで繰り返しパターンを積極的に検索し、ユーザーに送信する前に圧縮を解除し、ユーザーのブラウザに到達した後に圧縮を解除します。その結果、これらのリソースがさらに大幅に削減され、ダウンロード時間が短縮されます。

  • gzip と Brotli は、テキストベースのアセット(CSS、JavaScript、HTML)で最大限の効果を発揮する、よく使用される圧縮アルゴリズムです。
  • 最新のブラウザはすべて gzip 圧縮と Brotli 圧縮をサポートしており、Accept-Encoding HTTP リクエスト ヘッダーで両方のサポートをアドバタイズします。
  • 圧縮を有効にするようにサーバーを設定する必要があります。ウェブサーバー ソフトウェアでは、多くの場合、テキストベースのリソースを圧縮するモジュールがデフォルトで有効になっています。
  • gzip と Brotli の両方を微調整して、圧縮レベルを調整することで圧縮率を改善できます。gzip の場合、圧縮設定は 1 ~ 9 の範囲で、9 が最適です。Brotli の場合、この範囲は 0 ~ 11 で、11 が最適です。ただし、圧縮設定が高いほど時間がかかります。リソースが動的に圧縮される場合(リクエスト時)、範囲の中央の設定は、圧縮率と速度の間で最適なトレードオフを提供します。ただし、静的圧縮は可能です。これは、レスポンスが事前に圧縮されるため、各圧縮アルゴリズムで使用可能な最も積極的な圧縮設定を使用できます。
  • コンテンツ配信ネットワーク(CDN)は、通常、対象となるリソースの自動圧縮を提供します。CDN は動的圧縮と静的圧縮も管理できるため、圧縮に関する心配を減らすことができます。

gzipBrotli は、任意のバイトストリームに適用できる一般的な圧縮ツールです。内部的には、以前に検査したファイルのコンテンツの一部を記憶し、重複するデータ フラグメントを効率よく検索して置換することを試みます。

実際、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 を開き、[ネットワーク] パネルを開き、任意のページを読み込んで、ネットワーク パネルの一番下を確認します。

実際のサイズと転送サイズの DevTools の読み取り値。
すべてのページ リソースの転送サイズ(圧縮後)と、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 はリソースを圧縮できるだけでなく、非常に高速に圧縮できます。

これらのベースライン パフォーマンスのコンセプトをウェブサイトのアーキテクチャに組み込むことで、パフォーマンスの最適化が確実に行われるようにし、その後の最適化を優れたベースライン プラクティスの堅固な基盤の上に構築できるようにします。