Angular NgOptimizedImage ディレクティブの新機能

Alex Castle
Alex Castle

1 年以上前、Chrome Aurora チームAngular NgOptimizedImage ディレクティブをリリースしました。この指令は主に、Core Web Vitals 指標で測定されるパフォーマンスの改善に重点を置いています。一般的な画像の最適化やベスト プラクティスが、標準の <img> 要素ほどそれほど複雑ではないユーザー向け API にバンドルされています。

2023 年には、ディレクティブに新機能を追加しました。この投稿では、これらの新機能のうち特に重要なものについて説明します。各機能を優先した理由と、Angular アプリのパフォーマンス向上にどのように役立つかに重点を置いて説明します。

新機能

NgOptimizedImage は、以下の新機能を含め、時間の経過とともに大幅に改善されました。

塗りつぶしモード

width 属性と height 属性を指定して画像のサイズを調整することは、レイアウト シフトを減らすうえで極めて重要な最適化です。ブラウザは、画像のサイズを確保するために画像のアスペクト比を認識する必要があるためです。ただし、画像のサイズはアプリケーション デベロッパーにとっては追加作業であり、画像のユースケースによっては意味をなしません。

この緊張関係の解消に役立つのが、デベロッパー プレビュー後に画像コンポーネントに追加された最初の主要機能である塗りつぶしモードです。これにより、デベロッパーは画像のサイズを明示的に指定することなく、レイアウト シフトを発生させることなく画像を含めることができます。

塗りつぶしモードでは、画像サイズの要件は無効になり、画像に含まれている要素に合わせて画像のスタイルが自動的に設定されます。これにより、画像のアスペクト比とページ上の占有スペースが分離され、画像がページ レイアウトにどのように収まるかをより細かく制御できるようになります。

塗りつぶしモードでは、background-image CSS プロパティの代わりに NgOptimizedImage を使用することで、パフォーマンスが向上しています。前のコードサンプルに示すように、<div> などの要素内に background-image スタイルが設定される要素内に画像を配置してから、塗りつぶしモードを有効にします。<div> の CSS プロパティ object-fitobject-position を使用して、背景での画像の配置方法を制御します。

// Height and width are required
<img ngSrc="example.com" height="300" width="400">

// Unless you use fill mode!
<div style="width: 100vw; height: 50em; position: relative">
  <img ngSrc="example.com" fill>
</div>

ソースセットの生成

最も効果的な画像最適化手法の 1 つは、srcset 属性を使用して、アプリにアクセスするデバイスに適切なサイズの画像がダウンロードされるようにすることです。アプリ全体で srcset を使用すると、帯域幅の無駄を防ぎ、LCP Core Web Vitals を大幅に改善できます。

srcset 属性の欠点は、実装が面倒になる可能性があることです。srcset 値を手動で書き出すには、アプリ内の各画像要素に複数行のマークアップを追加し、srcset ごとに複数のカスタム URL を指定します。また、ブレークポイントのセットを決める必要がありますが、ブレークポイントは一般的なデバイスの画面密度とビューポート サイズの両方を表す可能性があるため、複雑です。

そのため、NgOptimizedImage ディレクティブにsrcset の自動生成を追加することは、リリース後の重要なマイルストーンでした。この追加により、画像のサイズ変更をサポートする CDN を使用するアプリケーションでは、NgOptimizedImage ディレクティブで生成されたすべての画像に、カスタマイズ可能な完全な srcset を自動的に追加できます。

sizes プロパティを設定するための簡素化された API が含まれています。この API を使用すると、各画像に正しいタイプの srcset が渡されます。sizes 属性を含めない場合は、画像が固定サイズであることが想定されており、次のように密度依存の srcset を取得する必要があります。

<img src="www.example.com/image.png" srcset="www.example.com/image.png?w=400 1x, www.example.com/image.png?w=800 2x" >

このような srcset により、ユーザーのデバイスのピクセル密度を考慮したサイズで画像が配信されるようになります。

一方、sizes プロパティを含めると、NgOptimizedImage は、このデフォルトのブレークポイント リストを使用して、多くの一般的なデバイスと画像サイズのブレークポイントを含むレスポンシブ srcset を生成します。

[16, 32, 48, 64, 96, 128, 256, 384, 640, 750, 828, 1080, 1200, 1920, 2048, 3840]

事前接続の生成

LCP を改善するには、ユーザーが LCP 画像のダウンロードに費やす時間を短縮することが重要です。前のセクションでは、srcset がサイズの小さい画像ファイルの転送にどのように役立つかについて説明しましたが、同様に重要な最適化は、できるだけ早く転送を開始することです。これを行う方法の 1 つは、link rel="preconnect" タグを使用してイメージドメインへの接続を開始することです。

当初から、LCP イメージのドメインへの事前接続に失敗した場合、NgOptimizedImage は警告を表示しますが、この警告は理想的なソリューションではありません。問題を解決するためだけに、この警告を使用します。今では NgOptimizedImage が自動の事前接続生成を使用して、まさにこれを実現しています。

この機能をサポートするために、Google は静的コード分析を使用して NgOptimizedImage ローダーでイメージドメインを検出し、そのドメインの preconnect リンクタグを自動的に生成しています。手動での事前接続リンクが必要になる場合もありますが、ほとんどの場合、自動事前接続を使用すると、画像のパフォーマンスを向上させるために必要な手順が 1 つ減ります。

カスタム ローダのサポートの強化

NgOptimizedImage の重要な要素はローダ アーキテクチャです。このアーキテクチャでは、アプリケーションの画像 CDN に合わせた URL をディレクティブが自動的に生成できます。広く使用されている CDN のために、組み込みのローダーのセットが含まれています。また、NgOptimizedImage をほぼすべての画像ホスティング ソリューションと統合できるカスタム ローダの使用も提供しています。

リリース時、これらのカスタム ローダはスコープが制限されており、image 要素から width 属性を読み取ることしかできませんでした。ユーザーからのフィードバックに応じて、カスタマイズ可能な loaderParams データ構造のサポートを追加しました。これにより、任意のデータを画像要素からカスタム ローダに渡すことができます。拡張により、アプリケーションのイメージ インフラストラクチャが必要とするだけのシンプルなローダーから複雑なローダーまで、カスタムのローダーが実現します。

次の例は、単純なカスタム ローダで loaderParams API を使用して、2 つの代替イメージ ドメインを選択する方法を示しています。

const myCustomLoader = (config: ImageLoaderConfig) => {
  if (config.loaderParams?.alternateDomain) {
    return `https://alternate.domain.com/images/${config.src}`
  }
  return `https://primary.domain.com/images/${config.src}`;
};

より複雑なカスタム ローダの例については、Angular のドキュメントをご覧ください。

画像のパフォーマンスに関するガイダンスを拡張

これまで Angular に追加された画像のパフォーマンス アラートは、すべて NgOptimizedImage ディレクティブに含まれていました。アプリでこのディレクティブを使用していない場合、画像のパフォーマンスの問題に関するガイダンスは表示されません。

Angular 17 では、画像のパフォーマンスに関するガイダンスの範囲が拡大され、すべての Angular アプリが含まれるようになります。LCP 画像の遅延読み込みや、ページに対して大きすぎるファイルのダウンロードなど、パフォーマンスを損なう誤りであることがわかっている画像パターンを検出した場合、NgOptimizedImage を使用していない場合でも通知されます。

画像のパフォーマンスはすべてのアプリにとって重要です。Google は、Angular アプリでよくあるミスを防ぐためのガードレールの構築に引き続き取り組んでいきます。

今後の展望

NgOptimizedImage の今後の機能セットについては、すでに着実に開発を進めています。画像のパフォーマンスは依然として Google の中心的な懸念事項ですが、デベロッパー エクスペリエンスを向上させる機能も追加し、NgOptimizedImage が Angular アプリケーションに画像を含めるための魅力的なオプションであり続けるようにしたいと考えています。

優先して取り組んでいる機能の一つに、画像のプレースホルダがあります。これらは、ウェブ アプリケーションでの画像読み込みの見栄えを良くするためによく使用されますが、正しく実装しないとパフォーマンスに悪影響を及ぼす可能性があります。パフォーマンス重視のイメージ プレースホルダ システムを NgOptimizedImage に構築したいと考えています。今後のお知らせについては、ブログをご覧ください。