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。](https://developer.chrome.com/static/blog/angular-image-directive/image/lcp-angular-websites-th-313c9b6e8afd2.png?authuser=19&hl=zh-tw)
查看 Core Web Vitals 分數時,達到「良好」LCP 門檻的 Angular 來源仍需要處理。2022 年 6 月,只有 18.74% 的 Angular 網站在行動裝置上的 LCP 表現良好。在行動版和電腦上,超過 70% 的網頁都是 LCP 元素,因此未最佳化的 LCP 圖片可能是 LCP 較差的主要原因之一。
Angular 圖片指令旨在協助提高這些數字。
NgOptimizedImage 指令的 MVP
Angular 圖片指令的 MVP 是根據 Aurora 至今所打造的圖像元件,並依此調整設計,以因應 Angular 的用戶端轉譯體驗。目前多數標準的圖片最佳化問題都能透過以下任一方法解決:
- 提供強大的預設值。
- 擲回錯誤或警告,確保符合最佳做法。
設計重點如下:
智慧型延遲載入
載入網頁時使用者看不到的圖片 (例如需捲動位置的圖片或隱藏的輪轉介面圖片),建議採用延遲載入方式。延遲載入功能可釋放瀏覽器資源來載入其他重要文字、媒體或指令碼。大多數圖片都不重要,而且應該延遲載入,但只有 7.8% 的網頁在 2021 年使用了原生延遲載入功能。
根據預設,Angular 圖片指令會延遲載入不重要的圖片,而且只會立即載入特別標示為
priority
的圖片。這可確保大多數圖片呈現最佳載入行為。優先排序重要圖片
新增資源提示 (例如
preload
或preconnect
) 安排優先載入重要圖片,是建議的最佳做法。不過大多數應用程式都不會使用這類程式。根據 2021 年的 Web Almanac 資料,只有 12.7% 的行動版網頁使用預先連線提示,只有 22.1% 的行動版網頁使用預先載入提示。當圖片標示為優先順序時,Image 指令會在兩個正面動作。
在開發模式下,指令也會使用 PerformanceObserver API,驗證 LCP 映像檔是否已如預期標示為
priority
。如未標示priority
,系統會擲回錯誤,指示開發人員將priority
屬性新增至 LCP 圖片。最終,這種自動化與合規性結合可確保 LCP 圖片具有
preconnect
提示和fetchpriority
屬性值high
,而且不會延遲載入。對熱門圖片工具的最佳化設定
建議 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 都採用建議的圖片格式和壓縮設定。
內建錯誤和警告
除了上述的內建最佳化功能外,這個指令也有內建檢查功能,可確保開發人員遵循圖片標記中的建議最佳做法。圖片指令會執行下列檢查。
未定義圖片的大小:如果圖片標記未定義明確寬度和高度,圖片指令會擲回錯誤。未尺寸的圖片可能會造成版面配置位移,影響網頁的「累計版面配置位移 (CLS)」指標。為了避免這種情況,我們建議的最佳做法是為圖片指定
width
和height
屬性。顯示比例:圖片指令會擲回錯誤,讓開發人員知道 HTML 中定義的
width
:height
長寬比是否接近實際顯示圖片的實際顯示比例。這可能會導致圖片畫面變形。發生這種情況可能是因為- 您輸入了錯誤的尺寸 (寬度或高度),或
- 如果已在 CSS 中以百分比定義一個維度,但不使用另一個 (例如,
width: 100%
需要height: auto
才能確保圖片同時放大兩個尺寸)。
超大型圖片:如果圖片未定義
srcset
,且內建圖片遠大於算繪圖片,指令中會顯示警告,說明srcset
和sizes
屬性的使用狀態。圖片密度:如果您嘗試在
srcset
中加入像素密度超過3x
的圖片,指令就會擲回錯誤。一般來說,我們不建議使用高於2x
的描述元,因為強制高解析度行動裝置下載大型圖片會帶來非預期的結果。此外,人類的眼睛無法看出 2 倍以上。
挑戰
設計 NgOptimizedImage
時,主要的挑戰是調整圖片最佳化策略,以便在用戶端架構中運作。Next.js 上的預設顯示體驗為伺服器端轉譯 (SSR) 或靜態網站產生 (SSG),而 Angular 則為用戶端轉譯 (CSR)。雖然 Angular 支援 SSR 程式庫 (angular/universal),- 大多數 Angular 應用程式 (約 60%) 都會使用 CSR。
圖片指令是完全專為 CSR 打造,以符合 Angular 應用程式中的一般用途。這讓他們設定了額外的限制,而團隊必須重新思考如何針對 CSR 應用程式建立特定的最佳化方式。
可能會遇到的挑戰如下:
支援資源提示
預先載入重要資產,可協助瀏覽器提早發現這類資產。不過,在 Angular 應用程式中納入資源提示非常複雜,原因如下:
手動新增:開發人員很難手動新增
preload
資源提示。Angular 只會針對整個專案或網站中的所有路徑使用一個共用 index.html 檔案。因此,每個路線 (至少服務時間) 的文件<head>
相同。在<head>
中新增任何preload
提示,代表系統會為所有路徑預先載入資源,即使位置非必要。因此,我們不建議手動新增preload
提示。在轉譯期間自動新增:使用架構在 CSR 應用程式中算繪時,使用架構在文件標題中新增預先載入提示並不能提供協助。因為在下載及執行 JavaScript 後才顯示,所以
<head>
會太晚轉譯為任何值。如果是第一個版本的指令,系統會結合使用
preconnect
提示和fetchpriority
提示,以優先圖片而非preload
。不過,Aurora 目前正在與 Angular CLI 團隊合作,在建構期間自動插入資源提示,敬請期待!最佳化伺服器上的圖片大小和格式
由於 Angular 應用程式通常是在用戶端轉譯,檔案系統中的圖片無法依要求時壓縮及提供。因此,建議您使用圖片 CDN 壓縮圖片,並將其轉換為隨選 WebP 或 AVIF 等新型格式。
雖然指令不會強制使用圖片 CDN,但我們強烈建議將這類指令與指令及其內建載入器搭配使用,確保使用正確的設定選項。
影響
以下示範呈現 Angular 圖片指令對圖片效能產生的差異。並比較兩個網站:
網站 One:使用原生 <img>
元素,搭配透過 Imgix CDN 放送的圖片 (含預設設定選項)。
網站二:所有圖片都須使用圖片指令。其中也包括指令擲回的警告或錯誤直接建議的最佳化方式。
![幻燈片比較:含有原生圖片代碼的網站 One 與含有 Angular 圖片指令的網站 2。](https://developer.chrome.com/static/blog/angular-image-directive/image/filmstrip-comparison-web-c03e5b7f51387.png?authuser=19&hl=zh-tw)
團隊與合作夥伴攜手合作,驗證映像檔指令對真實企業 Angular 應用程式的效能影響。
而其中一個合作夥伴就是 Land's End。他們認為自己的網站應該是良好的測試,才能帶來實際應用程式可能獲得的成效。
Lighthouse 研究室測試在使用映像檔指令前後,在其品質確保環境上執行。在電腦上,LCP 的中位數從 12.0 秒減少至 3.0 秒,LCP 提升了 75%。在行動裝置上,LCP 指標的中位數則從 20.2 秒降低至 12.0 秒 (40.6%)。
未來發展藍圖
以上只是 Angular 圖片指令設計的第一份設計。我們計劃在未來版本中加入許多其他功能,包括:
強化回應式圖片支援:
NgOptimizedImage
目前支援使用srcset
,但每張圖片都必須手動提供srcset
和sizes
屬性。日後,指令可以自動產生srcset
和sizes
屬性。自動插入資源提示
您可以整合 Angular CLI,以便為重要的 LCP 映像檔產生預先連線及預先載入標記。
支援 Angular SSR
MVP 版本的設計考量到 Angular CSR 的限制,但也值得一試,探索 Angular SSR (angular/通用) 的圖片最佳化解決方案。
改善開發人員體驗
使用
NgOptimizedImage
時,每張圖片都必須指定width
和height
屬性。不過,有些開發人員可能覺得為每張圖片指定這些圖片感到厭煩。在下一次疊代作業中,可望改善開發人員體驗,如下所示:- 支援不需明確定義寬度/高度的其他模式 (類似 Next.js 中的「
fill
」圖片版面配置選項)。 - 使用 CLI 整合功能決定圖片的實際尺寸,自動設定本機圖片的寬度和高度。
- 支援不需明確定義寬度/高度的其他模式 (類似 Next.js 中的「
結論
從開發人員預覽版 14.2.0 版開始,開發人員可以分階段使用 Angular 圖片指令。試試「NgOptimizedImage
」並提供意見!
特別感謝 Katie Hempenius 和 Alex Castle 的貢獻。