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

アレックス キャッスル
Alex Castle

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

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

新しい機能と特長

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

塗りつぶしモード

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

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

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

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

// 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 を指定することを意味します。また、ブレークポイントのセットを決める必要があり、これは一般的なデバイスの画面密度とビューポート サイズの両方を表す可能性があるため、複雑です。

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

sizes プロパティを設定するための簡素化された 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" タグを使用してイメージドメインへの接続をジャンプ開始することです。

最初から、NgOptimizedImage は、LCP イメージのドメインへの事前接続に失敗した場合に警告を表示していましたが、警告は理想的な解決策ではありません。問題を修正するだけです。これが、現在 NgOptimizedImage が行っている自動事前接続生成によって実現したものです。

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

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

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

リリース時点では、これらのカスタム ローダーのスコープは制限されており、画像要素から 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 アプリでよくあるミスを防ぐためのガードレールを構築していきます。

今後の展望

Google はすでに、NgOptimizedImage 向けの次の機能セットの開発に取り組んでいます。画像のパフォーマンスは依然として主要な関心事ですが、開発者エクスペリエンスを向上させる機能も追加して、NgOptimizedImage が Angular アプリケーションに画像を含めるための魅力的なオプションであり続けるようにしたいと考えています。

優先して取り組んでいる機能の一つに、画像のプレースホルダがあります。これらは一般に、ウェブ アプリケーションで画像の読み込みをより見やすくするために使用されますが、正しく実装しないとパフォーマンスが低下する可能性があります。パフォーマンス重視の画像プレースホルダ システムを NgOptimizedImage に組み込みたいと考えています。今後の発表については、Google のブログをご覧ください。