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

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

データ圧縮の概要

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

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

  • 圧縮とは、より少ないビットで情報をエンコードするプロセスです。
  • 不要なデータの除去は必ず最良の結果に結び付きます。
  • さまざまな圧縮手法とアルゴリズムがあります。
  • 最適な圧縮を実現するにはさまざまな技術が必要になります。

データサイズを縮小する処理のことをデータ圧縮と呼びます。圧縮率、圧縮速度、さまざまな圧縮アルゴリズムに必要なメモリを向上させるために、多くのユーザーがアルゴリズム、技術、最適化に貢献してきました。

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

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

# 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 を開いて [Network] パネルを開き、選択したページを読み込み、ネットワーク パネルの一番下を確認します。

実際のサイズと転送サイズの 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 はリソースを圧縮できるだけでなく、非常に迅速に圧縮できるからです。

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