画像のパフォーマンス

画像は、ウェブ上で最もサイズが大きく最も普及しているリソースです。そのため、画像を最適化すると、ウェブサイトのパフォーマンスが大幅に向上します。ほとんどの場合、画像の最適化とは、バイト数を減らしてネットワーク時間を短縮することを意味しますが、ユーザーのデバイスに適したサイズの画像を配信することで、ユーザーに送信されるバイト数を最適化することもできます。

画像は、<img> 要素または <picture> 要素、または CSS の background-image プロパティを使用してページに追加できます。

イメージサイズ

画像リソースを使用する際に最初に行う最適化は、画像を正しいサイズで表示することです。この場合の「サイズ」という用語は、画像のサイズを指します。他の変数を考慮しないで、500 x 500 ピクセルのコンテナに表示される画像の最適なサイズは 500 x 500 ピクセルです。たとえば、正方形の 1, 000 ピクセルの画像を使用すると、画像は必要なサイズの 2 倍になります。

ただし、適切な画像サイズの選択には多くの変数があり、すべてのケースで適切な画像サイズを選択することは非常に複雑です。2010 年に iPhone 4 がリリースされたとき、画面解像度(640x960)は iPhone 3 の 2 倍(320x480)でした。ただし、iPhone 4 の画面の物理サイズは iPhone 3 とほぼ同じです。

すべてのコンテンツを高解像度で表示すると、テキストと画像が大幅に小さくなります(正確には以前の半分)。代わりに、1 ピクセルが 2 つのデバイス ピクセルになりました。これはデバイスのピクセル比(DPR)と呼ばれます。iPhone 4 と、それ以降にリリースされた多くの iPhone モデルの DPR は 2 でした。

前述の例に戻ると、デバイスの DPR が 2 で、画像が 500 x 500 ピクセルのコンテナに表示される場合は、正方形の 1,000 ピクセルの画像(元のサイズ)が最適なサイズになります。同様に、デバイスの DPR が 3 の場合、1500 ピクセルの正方形の画像が最適なサイズになります。

srcset

<img> 要素は srcset 属性をサポートしています。この属性を使用すると、ブラウザで使用できる画像ソースのリストを指定できます。指定する各画像ソースには、画像の URL と、幅またはピクセル密度記述子を含める必要があります。

<img
  alt="An image"
  width="500"
  height="500"
  src="/image-500.jpg"
  srcset="/image-500.jpg 1x, /image-1000.jpg 2x, /image-1500.jpg 3x"
>

上の HTML スニペットは、ピクセル密度記述子を使用して、DPR が 1 のデバイスでは image-500.png、DPR が 2 のデバイスでは image-1000.jpg、DPR が 3 のデバイスでは image-1500.jpg を使用するようにブラウザにヒントを提供します。

一見簡単そうに見えますが、特定のページに最適な画像を選択する際に考慮すべき点は、画面の DPR だけではありません。ページのレイアウトも考慮すべき点です。

sizes

前のソリューションは、すべてのビューポートで同じ CSS ピクセルサイズで画像を表示する場合にのみ機能します。多くの場合、ページのレイアウト(およびそれに伴うコンテナのサイズ)は、ユーザーのデバイスによって異なります。

sizes 属性を使用すると、ソースサイズのセットを指定できます。各ソースサイズは、メディア条件と値で構成されます。sizes 属性は、画像の目的の表示サイズを CSS ピクセル単位で記述します。srcset 幅記述子と組み合わせると、ブラウザはユーザーのデバイスに最適な画像ソースを選択できます。

<img
  alt="An image"
  width="500"
  height="500"
  src="/image-500.jpg"
  srcset="/image-500.jpg 500w, /image-1000.jpg 1000w, /image-1500.jpg 1500w"
  sizes="(min-width: 768px) 500px, 100vw"
>

上の HTML スニペットでは、srcset 属性で、ブラウザが選択できる画像候補のリストをカンマ区切りで指定しています。リスト内の各候補は、画像の URL と、画像の固有の幅を示す構文で構成されます。画像の元のサイズは、その寸法です。たとえば、記述子 1000w は、画像の本質的な幅が 1, 000 ピクセルであることを示します。

ブラウザは、この情報を使用して sizes 属性のメディア条件を評価します。この場合、デバイスのビューポートの幅が 768 ピクセルを超える場合は、画像を 500 ピクセルの幅で表示するように指示されます。小さいデバイスでは、画像は 100vw(ビューポートの全幅)で表示されます。

ブラウザは、この情報を srcset 画像ソースのリストと組み合わせて、最適な画像を見つけることができます。たとえば、画面幅が 320 ピクセルで DPR が 3 のモバイル デバイスを使用している場合、画像は 320 CSS pixels x 3 DPR = 960 device pixels に表示されます。この例では、最も近いサイズの画像は image-1000.jpg で、固有の幅は 1, 000 ピクセル(1000w)です。

ファイル形式

ブラウザは、さまざまな画像ファイル形式をサポートしています。WebPAVIF などの最新の画像形式は、PNG や JPEG よりも圧縮率が高く、画像ファイルサイズを小さくしてダウンロード時間を短縮できます。最新の形式で画像を配信することで、リソースの読み込み時間を短縮でき、Largest Contentful Paint(LCP)を短縮できる可能性があります。

WebP は、すべての最新ブラウザで動作する広くサポートされている形式です。WebP は、JPEG、PNG、GIF よりも圧縮率が高いことが多く、非可逆圧縮と可逆圧縮の両方に対応しています。また、WebP は非可逆圧縮を使用している場合でもアルファ チャンネルの透明度をサポートしています。これは JPEG コーデックにはない機能です。

AVIF は新しい画像形式であり、WebP ほど広くサポートされていませんが、ブラウザ間で比較的良好なサポートを受けています。AVIF は非可逆圧縮と可逆圧縮の両方をサポートしており、テストでは、JPEG と比較して 50% を超える節約が示されています。AVIF には、広色域(WCG)ハイ ダイナミック レンジ(HDR)機能も用意されています。

圧縮

画像には、次の 2 種類の圧縮があります。

  1. 非可逆圧縮
  2. ロスレス圧縮

非可逆圧縮は、量子化によって画像の精度を低下させることで機能し、クロマ サブサンプリングを使用して追加の色情報が破棄される場合があります。非可逆圧縮は、ノイズや色の多い高密度画像(通常は、類似したコンテンツの写真や画像)に最も効果的です。これは、不可逆圧縮によって生成されるアーティファクトが、このような詳細な画像では認識されにくいためです。ただし、線画、同様に鮮明なディテール、テキストなど、シャープなエッジを含む画像では、非可逆圧縮の効果が低下する可能性があります。非可逆圧縮は、JPEG、WebP、AVIF の画像に適用できます。

ロスレス圧縮は、データの損失なしで画像を圧縮することでファイルサイズを削減します。ロスレス圧縮では、隣接するピクセルとの差異に基づいてピクセルを記述します。可逆圧縮は、GIF、PNG、WebP、AVIF の画像形式で使用されます。

画像を圧縮するには、SquooshImageOptim、または画像最適化サービスを使用します。圧縮する場合、すべてのケースに適した汎用設定はありません。推奨されるアプローチは、画質とファイルサイズの間で適切な妥協点を見つけるまで、さまざまな圧縮レベルをテストすることです。一部の高度な画像最適化サービスでは、この作業が自動的に行われますが、すべてのユーザーにとって費用対効果がよいとは限りません。

<picture> 要素

<picture> 要素を使用すると、複数の画像候補を柔軟に指定できます。

<picture>
  <source type="image/avif" srcset="image.avif">
  <source type="image/webp" srcset="image.webp">
  <img
    alt="An image"
    width="500"
    height="500"
    src="/image.jpg"
  >
</picture>

<picture> 要素内で <source> 要素を使用すると、AVIF 画像と WebP 画像のサポートを追加できますが、ブラウザが最新の形式をサポートしていない場合は、互換性の高い従来の画像形式にフォールバックします。このアプローチでは、一致する最初の <source> 要素がブラウザによって選択されます。その形式で画像をレンダリングできる場合は、その画像を使用します。それ以外の場合は、ブラウザは次の指定された <source> 要素に移動します。上記の HTML スニペットでは、AVIF 形式が WebP 形式よりも優先され、AVIF 形式と WebP 形式のどちらもサポートされていない場合は JPEG 形式にフォールバックします。

<picture> 要素には、その中にネストされた <img> 要素が必要です。altwidthheight の各属性は <img> で定義され、どの <source> が選択されているかに関係なく使用されます。

<source> 要素は、mediasrcsetsizes の各属性もサポートしています。前述の <img> の例と同様に、これらは、さまざまなビューポートで選択する画像をブラウザに指示します。

<picture>
  <source
    media="(min-resolution: 1.5x)"
    srcset="/image-1000.jpg 1000w, /image-1500.jpg 1500w"
    sizes="(min-width: 768px) 500px, 100vw"
  >
  <img
    alt="An image"
    width="500"
    height="500"
    src="/image-500.jpg"
  >
</picture>

media 属性はメディア条件を受け取ります。上の例では、デバイスの DPR がメディア条件として使用されています。DPR が 1.5 以上のデバイスは、最初の <source> 要素を使用します。<source> 要素は、ビューポートの幅が 768 ピクセルを超えるデバイスでは、選択した画像候補が 500 ピクセルの幅で表示されることを伝えます。小さいデバイスでは、viewport の幅全体が占有されます。media 属性と srcset 属性を組み合わせることで、使用する画像をより細かく制御できます。

次の表に、いくつかのビューポート幅とデバイスのピクセル比率を評価した結果を示します。

ビューポートの幅(ピクセル) 1 DPR 1.5 DPR 2 DPR 3 DPR
320 500.jpg 500.jpg 500.jpg 1000.jpg
480 500.jpg 500.jpg 1000.jpg 1500.jpg
560 500.jpg 1000.jpg 1000.jpg 1500.jpg
1024 500.jpg 1000.jpg 1000.jpg 1500.jpg
1920 500.jpg 1000.jpg 1000.jpg 1500.jpg

DPR が 1 のデバイスは image-500.jpg 画像をダウンロードします。これには、ほとんどのデスクトップ ユーザーが含まれます。デスクトップ ユーザーは、画像を幅 500 ピクセルの外部サイズで表示します。一方、DPR が 3 のモバイル ユーザーは、DPR が 3 のデスクトップ デバイスで使用されているものと同じ、より大きな image-1500.jpg をダウンロードする可能性があります。

<picture>
  <source
    media="(min-width: 561px) and (min-resolution: 1.5x)"
    srcset="/image-1000.jpg 1000w, /image-1500.jpg 1500w"
    sizes="(min-width: 768px) 500px, 100vw"
  >
  <source
    media="(max-width: 560px) and (min-resolution: 1.5x)"
    srcset="/image-1000-sm.jpg 1000w, /image-1500-sm.jpg 1500w"
    sizes="(min-width: 768px) 500px, 100vw"
  >
  <img
    alt="An image"
    width="500"
    height="500"
    src="/image-500.jpg"
  >
</picture>

この例では、<picture> 要素を調整して、DPR が高いワイドデバイスに別の画像を使用する <source> 要素を追加しています。

ビューポートの幅(ピクセル) 1 DPR 1.5 DPR 2 DPR 3 DPR
320 500.jpg 500.jpg 1000-sm.jpg 1000-sm.jpg
480 500.jpg 500.jpg 1000-sm.jpg 1500-sm.jpg
560 500.jpg 1000-sm.jpg 1000-sm.jpg 1500-sm.jpg
1024 500.jpg 1000.jpg 1000.jpg 1500.jpg
1920 500.jpg 1000.jpg 1000.jpg 1500.jpg

この追加のクエリにより、image-1000-sm.jpgimage-1500-sm.jpg が小さいビューポートに表示されることがわかります。この追加情報により、デスクトップ デバイスの画質を損なうことなく、画像をさらに圧縮できます。このサイズと密度では圧縮アーティファクトが目立たないためです。

また、srcset 属性と media 属性を調整することで、小さなビューポートに大きな画像を配信しないようにすることもできます。

<picture>
  <source
    media="(min-width: 561px)"
    srcset="/image-500.jpg, /image-1000.jpg 2x, /image-1500.jpg 3x"
  >
  <source
    media="(max-width: 560px)"
    srcset="/image-500.jpg 1x, /image-1000.jpg 2x"
  >
  <img
    alt="An image"
    width="500"
    height="500"
    src="/image-500.jpg"
  >
</picture>

上記の HTML スニペットでは、デバイスのピクセル比記述子に置き換えて、幅記述子が削除されています。モバイル デバイスで配信される画像は、DPR が 3 のデバイスでも /image-500.jpg または /image-1000.jpg に制限されます。

複雑さを管理する方法

レスポンシブ画像を使用すると、各画像にさまざまなサイズと形式が用意される場合があります。上の例では、各サイズのバリエーションが使用されていますが、AVIF と WebP は除外されています。バリエーションの数はいくつにすべきですか?多くのエンジニアリングの問題と同様に、答えは「状況次第」になる傾向があります。

最適な画像を配信するためにバリエーションをできるだけ多く用意したくなるかもしれませんが、画像バリエーションを追加するたびに費用が発生し、ブラウザ キャッシュの使用効率が低下します。バリエーション数が 1 つの場合、すべてのユーザーに同じ画像が提供されるため、非常に効率的にキャッシュに保存できます。

一方、バリエーションが多い場合は、バリエーションごとに別のキャッシュ エントリが必要になります。バリアントのキャッシュエントリの有効期限が切れて、オリジン サーバーから画像を再度取得する必要がある場合、サーバー費用が増加し、パフォーマンスが低下する可能性があります。

また、バリエーションが増えるにつれて HTML ドキュメントのサイズも増加します。画像ごとに数キロバイトの HTML を送信することになる可能性があります。

Accept リクエスト ヘッダーに基づいて画像を提供する

Accept HTTP リクエスト ヘッダーは、ユーザーのブラウザが認識するコンテンツ タイプをサーバーに通知します。この情報は、HTML レスポンスに余分なバイトを追加することなく、最適な画像形式を提供するのに使用できます。

if (request.headers.accept) {
  if (request.headers.accept.includes('image/avif')) {
    return reply.from('image.avif');
  } else if (request.headers.accept.includes('image/webp')) {
    return reply.from('image.webp');
  }
}

return reply.from('image.jpg');

上記の HTML スニペットは、サーバーの JavaScript バックエンドに追加して最適な画像形式を選択して提供するコードを簡素化したものです。リクエスト Accept ヘッダーに image/avif が含まれている場合、AVIF 画像が提供されます。それ以外の場合、Accept ヘッダーに image/webp が含まれている場合は、WebP 画像が提供されます。これらの条件のいずれも満たされない場合、JPEG 画像が提供されます。

ほとんどのタイプのウェブサーバーで、Accept リクエスト ヘッダーの内容に基づいてレスポンスを変更できます。たとえば、mod_rewrite を使用して Accept ヘッダーに基づいて Apache サーバーで画像リクエストを書き換えることができます。

これは、画像コンテンツ配信ネットワーク(CDN)で見られるような動作と類似しています。画像 CDN は、画像を最適化し、ユーザーのデバイスとブラウザに基づいて最適な形式を送信するための優れたソリューションです。

重要なのは、バランスを取り、適切な数の候補画像を生成し、ユーザー エクスペリエンスへの影響を測定することです。画像によって結果は異なります。各画像に適用される最適化は、ページ内のサイズとユーザーが使用しているデバイスによって異なります。たとえば、全幅のヒーロー画像では、e コマースの商品リスティング ページの縮小画像よりも多くのバリエーションが必要になる場合があります。

遅延読み込み

loading 属性を使用して、ビューポートに表示された画像を遅延読み込みするようにブラウザに指示できます。属性値が lazy の場合、画像がビューポート内(またはビューポートの近く)になるまで画像をダウンロードしないようにブラウザに指示します。これにより帯域幅が節約され、ブラウザはビューポート内にある重要なコンテンツのレンダリングに必要なリソースを優先できます。

decoding

decoding 属性は、画像のデコード方法をブラウザに指示します。値が async の場合、画像を非同期でデコードできることをブラウザに伝え、他のコンテンツのレンダリング時間を短縮できます。値が sync の場合、画像は他のコンテンツと同じタイミングで表示される必要があります。デフォルト値の auto では、ブラウザがユーザーにとって最適なものを決定します。

画像のデモ

理解度テスト

非可逆圧縮をサポートしている画像形式はどれですか。

.GIF のいずれかの形式で保存します。
正解です。
JPEG です。
もう一度お試しください。
PNG など
正解です。
WebP。
正解です。
AVIF。
正解です。

非可逆圧縮をサポートする画像形式はどれですか?

.GIF のいずれかの形式で保存します。
もう一度お試しください。GIF 形式は 256 色の限定されたパレットしかサポートしていませんが、GIF に変換する前に非可逆エンコードを行う必要があります。
JPEG です。
正解です。
PNG など
もう一度お試しください。
WebP。
正解です。
AVIF。
正解です。

幅記述子(1000w など)は、srcset 属性で指定された画像候補についてブラウザに何を伝えますか。

画像の外部幅。つまり、ページにスタイルが適用された後のレイアウト内の画像のサイズです。
もう一度お試しください。
画像の固有の幅(画像自体のサイズ)。
正解です。

sizes 属性は、適用先の <img> 要素についてブラウザに何を伝えますか。

ユーザーの現在のビューポートのサイズに基づいて、<img> 要素の srcset で指定された候補のどれを読み込むかを示すロジック。
正解です。
<img> 要素の srcset 属性から読み込まれる画像の固有の幅。
もう一度お試しください。

次に: 動画のパフォーマンス

画像はウェブで使用されるメディア タイプの中で最も普及しているものですが、パフォーマンスに関して考慮すべき唯一のタイプではありません。動画は、ウェブ全体で使用される一般的なメディアのもう 1 つのタイプであり、独自のパフォーマンスに関する考慮事項があります。このコースの次のモジュールでは、動画の最適化と効率的な読み込み方法に関するテクニックについて説明します。