使用 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 的貢獻。