Angular NgOptimizedImage 指令新功能

Alex Castle
Alex Castle

大約一年前,Chrome Aurora 團隊推出了 Angular NgOptimizedImage 指令。這項指令主要著重於改善效能,以 Core Web Vitals 指標為評估依據。它將常見的圖片最佳化和最佳做法整合至面向使用者的 API,而這個 API 的複雜度與標準 <img> 元素相差無幾。

在 2023 年,我們為指令增添了新功能。這篇文章將說明這些新功能中最實質的部分,並著重說明我們選擇將各項功能列為優先的原因,以及這些功能如何有助於改善 Angular 應用程式的效能。

新功能

NgOptimizedImage 在不斷改進後,已加入下列新功能。

填充模式

透過提供 widthheight 屬性來調整圖片大小,是減少版面配置偏移的極為重要的最佳化方式,因為瀏覽器需要知道圖片的顯示比例,才能為圖片保留空間。不過,為圖片設定大小是應用程式開發人員的額外工作,且在某些圖片用途上並不合理。

為瞭解決這項問題,我們在開發人員預覽版後,為圖片元件新增了第一個主要功能:填滿模式。這是開發人員可以納入圖片的方式,無須明確指定圖片大小,也不會造成版面配置偏移。

在填滿模式下,系統會停用圖片大小規定,並自動為圖片套用樣式,讓圖片填滿包含它的元素。這麼做可將圖片的顯示比例與其在頁面上所占空間分開,讓您更能控管圖片如何配合網頁版面配置。

填充模式會使用 NgOptimizedImage,做為 background-image CSS 屬性的最佳替代方案。將圖片放入 <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>

產生 Srcset

使用 srcset 屬性是最有效的圖片最佳化技巧之一,可確保任何存取應用程式的裝置都能下載適當大小的圖片。在應用程式中使用 srcset 可避免浪費頻寬,並大幅改善 LCP Core Web Vital

srcset 屬性的缺點是實作起來可能很麻煩。手動輸入 srcset 值,就是在應用程式中的每個圖片元素中加入多行標記,並為每個 srcset 提供多個自訂網址。您也必須決定一組中斷點,這項作業相當複雜,因為中斷點可同時代表螢幕密度和常見裝置的檢視區大小。

因此,在 NgOptimizedImage 指令中加入自動 srcset 產生功能,是推出後的重要里程碑。有了這項功能,任何使用支援圖片重新調整大小的 CDN 的應用程式,都能在使用 NgOptimizedImage 指令產生的每張圖片中,自動加入完整且可自訂的 srcset。

我們已提供簡化的 API 來設定 sizes 屬性,用於確保每張圖片都能取得正確的 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 如何協助傳輸較小的圖片檔案,但同樣重要的最佳化方式,是盡快開始傳輸。其中一種方法是使用 link rel="preconnect" 標記,快速連結至圖片網域。

從一開始,如果您無法預先連線至 LCP 圖片的網域,NgOptimizedImage 就會發出警告,但警告並非理想的解決方案,我們寧可直接為您修正問題。而這正是 NgOptimizedImage 目前透過自動產生預先連結功能所執行的動作。

為支援這項功能,我們會使用靜態程式碼分析,嘗試在 NgOptimizedImage 載入器中偵測圖片網域,並為這些網域自動產生預連結連結代碼。在某些情況下,您可能仍需要手動預先連結,但對大多數使用者而言,自動預先連結可減少一道步驟,進而提升圖片品質。

強化自訂載入器的支援

NgOptimizedImage 的關鍵元素是載入器架構,可讓指令自動產生專為應用程式圖片 CDN 量身打造的網址。我們也為廣泛使用的 CDN 提供一組內建載入器。我們也提供自訂載入器,可讓您將 NgOptimizedImage 與幾乎所有圖片代管解決方案整合。

在推出時,這些自訂載入器的範圍受到限制,只能讀取圖片元素的 width 屬性。我們根據使用者意見回饋,新增了對可自訂 loaderParams 資料結構的支援,可將任意資料從圖片元素傳遞至自訂載入器。有了這項擴充功能,您可以根據應用程式的圖片基礎架構,設計簡單或複雜的自訂載入器。

以下範例說明簡單的自訂載入器如何使用 loaderParams API 在兩個替代圖片網域之間進行選擇:

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 應用程式。如今,即使您未使用 NgOptimizedImage,如果我們偵測到會影響效能的錯誤圖片模式 (例如延遲載入 LCP 圖片,或下載的檔案太大),也會通知您。

圖片效能對所有應用程式都很重要,我們很高興能持續建構防護機制,協助避免 Angular 應用程式發生常見錯誤。

展望未來

我們正努力開發 NgOptimizedImage 的下一組功能。雖然圖片效能仍是我們的主要關注重點,但我們也想新增可改善開發人員體驗的功能,確保 NgOptimizedImage 在 Angular 應用程式中加入圖片時,仍是吸引人的選項。

我們優先考量的功能之一是圖片預留位置。這些技術通常用於改善網頁應用程式中圖片的載入效果,但如果導入方式不正確,可能會影響效能。我們希望在 NgOptimizedImage 中建立以效能為優先的圖片預留位置系統。請密切關注我們的網誌,掌握後續公告!