使用 Angular Image 指令最佳化圖片

Kara Erickson
Kara Erickson
Leena Sohoni
Leena Sohoni

2022 年 5 月,Aurora 和 Angular 團隊宣布,他們會合作開發 Angular 的圖片指令。這項指令最近已納入 Angular v14.2 的開發人員預覽版。這篇文章說明新的圖片指令 NgOptimizedImage 如何支援 Angular 中的圖片最佳化功能。

背景

圖片是網頁使用者體驗中常見且重要的元素,有 99.9% 的網頁會產生一或多張圖片。圖片也是最主要的頁面比例因素,每頁圖片的中位數為 982 KB

圖片的數量和大小不斷增加,可能會降低網頁效能並影響網站體驗核心指標指標。在 79.4% 的電腦版網頁上,有一張圖片是 2021 年最大的內容繪製 (LCP) 元素。獲取最佳化圖片已成為我們許多人持續努力的方向。

Aurora 團隊認為,應運用架構的強大功能來解決常見的開發人員難題。他們首先要探討的是圖片最佳化空間,也就是 Next.js 圖片元件。他們認為這是一個測試園地,旨在改善圖像最佳化的開發人員體驗 (DX),是否能協助更多使用架構的應用程式達到效能。

Next.js 使用者 Leboncoin 產生第一組結果令人振奮,Leboncoin 在使用 next/image 後發現 LCP 大幅提升 (從 2.4 秒到 1.7 秒)。隨著 Next.js 來源的增加,達到 LCP 閾值後,社群中的 next/image 採用率有所提升。不久後,其他架構也會針對類似功能提出要求,其中一項是 Angular

因此,Aurora 諮詢 Angular 和 Nuxt,您可以針對這些架構設計圖片元件的原型。Nuxt 映像檔元件已於去年推出。現在發布 Angular 圖片指令 (NgOptimizedImage),為 Angular 預設提供圖片最佳化功能。

機會

Angular 是現今開發人員採用的頂尖 JavaScript 架構之一。超過 5 萬個來源在行動裝置和 HTTPArchive 使用這個項目,每週下載量將近 300 萬次

過去一年內用於 Angular 網站的 LCP。

查看 Core Web Vitals 分數時,達到「良好」LCP 門檻的 Angular 來源仍需要處理。2022 年 6 月,只有 18.74% 的 Angular 網站在行動裝置上的 LCP 表現良好。在行動版和電腦上,超過 70% 的網頁都是 LCP 元素,因此未最佳化的 LCP 圖片可能是 LCP 較差的主要原因之一。

Angular 圖片指令旨在協助提高這些數字。

NgOptimizedImage 指令的 MVP

Angular 圖片指令的 MVP 是根據 Aurora 至今所打造的圖像元件,並依此調整設計,以因應 Angular 的用戶端轉譯體驗。目前多數標準的圖片最佳化問題都能透過以下任一方法解決:

  • 提供強大的預設值。
  • 擲回錯誤或警告,確保符合最佳做法。

設計重點如下:

  1. 智慧型延遲載入

    載入網頁時使用者看不到的圖片 (例如需捲動位置的圖片或隱藏的輪轉介面圖片),建議採用延遲載入方式。延遲載入功能可釋放瀏覽器資源來載入其他重要文字、媒體或指令碼。大多數圖片都不重要,而且應該延遲載入,但只有 7.8% 的網頁在 2021 年使用了原生延遲載入功能。

    根據預設,Angular 圖片指令會延遲載入不重要的圖片,而且只會立即載入特別標示為 priority 的圖片。這可確保大多數圖片呈現最佳載入行為。

  2. 優先排序重要圖片

    新增資源提示 (例如preloadpreconnect) 安排優先載入重要圖片,是建議的最佳做法。不過大多數應用程式都不會使用這類程式。根據 2021 年的 Web Almanac 資料,只有 12.7% 的行動版網頁使用預先連線提示,只有 22.1% 的行動版網頁使用預先載入提示。

    當圖片標示為優先順序時,Image 指令會在兩個正面動作。

    • 這會將圖片的「擷取優先順序」設為 "high",這樣一來,瀏覽器就會知道圖片應下載高優先順序的圖片。
    • 在開發模式中,執行階段檢查會確認圖片來源已納入 preconnect 資源提示。

    在開發模式下,指令也會使用 PerformanceObserver API,驗證 LCP 映像檔是否已如預期標示為 priority。如未標示 priority,系統會擲回錯誤,指示開發人員將 priority 屬性新增至 LCP 圖片。

    最終,這種自動化與合規性結合可確保 LCP 圖片具有 preconnect 提示和 fetchpriority 屬性值 high,而且不會延遲載入。

  3. 對熱門圖片工具的最佳化設定

    建議 Angular 應用程式使用圖片 CDN,因為這類軟體預設通常提供最佳化服務。

    指令會鼓勵使用圖片 CDN,為開發人員提供特別有吸引力的開發人員體驗 (DX) 來在應用程式中進行設定。此指令支援載入器 API,可讓您定義 CDN 供應商和基準網址。設定完成後,您只需在標記中定義資產名稱。舉例來說,

    // in module providers:
    provideImgixLoader('https://mysite.net/assets/')
    
    // in markup
    <img ngSrc="image.png" >
    <img ngSrc="image2.png" >
    

    相當於加入下列圖片代碼,並減少開發人員必須為每張圖片加入的標記。

    <img src="https://mysite.net/assets/image.png">
    <img src="https://mysite.net/assets/image2.png">
    

    映像檔指令為內建載入器提供最適合熱門的圖片 CDN 設定。這些載入器會自動設定圖片網址的格式,確保每個 CDN 都採用建議的圖片格式和壓縮設定。

  4. 內建錯誤和警告

    除了上述的內建最佳化功能外,這個指令也有內建檢查功能,可確保開發人員遵循圖片標記中的建議最佳做法。圖片指令會執行下列檢查。

    1. 未定義圖片的大小:如果圖片標記未定義明確寬度和高度,圖片指令會擲回錯誤。未尺寸的圖片可能會造成版面配置位移,影響網頁的「累計版面配置位移 (CLS)」指標。為了避免這種情況,我們建議的最佳做法是為圖片指定 widthheight 屬性。

    2. 顯示比例:圖片指令會擲回錯誤,讓開發人員知道 HTML 中定義的 width:height 長寬比是否接近實際顯示圖片的實際顯示比例。這可能會導致圖片畫面變形。發生這種情況可能是因為

      1. 您輸入了錯誤的尺寸 (寬度或高度),或
      2. 如果已在 CSS 中以百分比定義一個維度,但不使用另一個 (例如,width: 100% 需要 height: auto 才能確保圖片同時放大兩個尺寸)。
    3. 超大型圖片:如果圖片未定義 srcset,且內建圖片遠大於算繪圖片,指令中會顯示警告,說明 srcsetsizes 屬性的使用狀態。

    4. 圖片密度:如果您嘗試在 srcset 中加入像素密度超過 3x 的圖片,指令就會擲回錯誤。一般來說,我們不建議使用高於 2x 的描述元,因為強制高解析度行動裝置下載大型圖片會帶來非預期的結果。此外,人類的眼睛無法看出 2 倍以上

挑戰

設計 NgOptimizedImage 時,主要的挑戰是調整圖片最佳化策略,以便在用戶端架構中運作。Next.js 上的預設顯示體驗為伺服器端轉譯 (SSR) 或靜態網站產生 (SSG),而 Angular 則為用戶端轉譯 (CSR)。雖然 Angular 支援 SSR 程式庫 (angular/universal),- 大多數 Angular 應用程式 (約 60%) 都會使用 CSR。

圖片指令是完全專為 CSR 打造,以符合 Angular 應用程式中的一般用途。這讓他們設定了額外的限制,而團隊必須重新思考如何針對 CSR 應用程式建立特定的最佳化方式。

可能會遇到的挑戰如下:

  1. 支援資源提示

    預先載入重要資產,可協助瀏覽器提早發現這類資產。不過,在 Angular 應用程式中納入資源提示非常複雜,原因如下:

    手動新增:開發人員很難手動新增 preload 資源提示。Angular 只會針對整個專案或網站中的所有路徑使用一個共用 index.html 檔案。因此,每個路線 (至少服務時間) 的文件 <head> 相同。在 <head> 中新增任何 preload 提示,代表系統會為所有路徑預先載入資源,即使位置非必要。因此,我們不建議手動新增 preload 提示。

    在轉譯期間自動新增:使用架構在 CSR 應用程式中算繪時,使用架構在文件標題中新增預先載入提示並不能提供協助。因為在下載及執行 JavaScript 後才顯示,所以 <head> 會太晚轉譯為任何值。

    如果是第一個版本的指令,系統會結合使用 preconnect 提示和 fetchpriority 提示,以優先圖片而非 preload。不過,Aurora 目前正在與 Angular CLI 團隊合作,在建構期間自動插入資源提示,敬請期待!

  2. 最佳化伺服器上的圖片大小和格式

    由於 Angular 應用程式通常是在用戶端轉譯,檔案系統中的圖片無法依要求時壓縮及提供。因此,建議您使用圖片 CDN 壓縮圖片,並將其轉換為隨選 WebP 或 AVIF 等新型格式。

    雖然指令不會強制使用圖片 CDN,但我們強烈建議將這類指令與指令及其內建載入器搭配使用,確保使用正確的設定選項。

影響

以下示範呈現 Angular 圖片指令對圖片效能產生的差異。並比較兩個網站:

網站 One:使用原生 <img> 元素,搭配透過 Imgix CDN 放送的圖片 (含預設設定選項)。

網站二:所有圖片都須使用圖片指令。其中也包括指令擲回的警告或錯誤直接建議的最佳化方式。

幻燈片比較:含有原生圖片代碼的網站 One 與含有 Angular 圖片指令的網站 2。

團隊與合作夥伴攜手合作,驗證映像檔指令對真實企業 Angular 應用程式的效能影響。

而其中一個合作夥伴就是 Land's End。他們認為自己的網站應該是良好的測試,才能帶來實際應用程式可能獲得的成效。

Lighthouse 研究室測試在使用映像檔指令前後,在其品質確保環境上執行。在電腦上,LCP 的中位數從 12.0 秒減少至 3.0 秒,LCP 提升了 75%。在行動裝置上,LCP 指標的中位數則從 20.2 秒降低至 12.0 秒 (40.6%)。

未來發展藍圖

以上只是 Angular 圖片指令設計的第一份設計。我們計劃在未來版本中加入許多其他功能,包括:

  • 強化回應式圖片支援:

    NgOptimizedImage 目前支援使用 srcset,但每張圖片都必須手動提供 srcsetsizes 屬性。日後,指令可以自動產生 srcsetsizes 屬性。

  • 自動插入資源提示

    您可以整合 Angular CLI,以便為重要的 LCP 映像檔產生預先連線及預先載入標記。

  • 支援 Angular SSR

    MVP 版本的設計考量到 Angular CSR 的限制,但也值得一試,探索 Angular SSR (angular/通用) 的圖片最佳化解決方案。

  • 改善開發人員體驗

    使用 NgOptimizedImage 時,每張圖片都必須指定 widthheight 屬性。不過,有些開發人員可能覺得為每張圖片指定這些圖片感到厭煩。在下一次疊代作業中,可望改善開發人員體驗,如下所示:

    1. 支援不需明確定義寬度/高度的其他模式 (類似 Next.js 中的「fill」圖片版面配置選項)。
    2. 使用 CLI 整合功能決定圖片的實際尺寸,自動設定本機圖片的寬度和高度。

結論

從開發人員預覽版 14.2.0 版開始,開發人員可以分階段使用 Angular 圖片指令。試試「NgOptimizedImage」並提供意見!

特別感謝 Katie Hempenius 和 Alex Castle 的貢獻。