2022 年 5 月,Aurora 和 Angular 團隊宣布將合作為 Angular 開發圖片指令。這項指令最近已在 Angular 第 14.2 版中發布開發人員預覽版。本文將說明新的圖片指令 NgOptimizedImage
如何支援 Angular 中的圖片最佳化功能。
背景
圖片是網路使用者體驗中常見且重要的元素,99.9% 的網頁都會產生一或多個圖片的要求。圖片也是影響網頁重量的最大因素,每個網頁的平均大小為 982 千位元組。
由於圖片的數量和大小不斷增加,可能會影響網頁效能,並影響網站體驗核心指標。在 2021 年,79.4% 的電腦版網頁的最大內容繪製 (LCP) 元素都是圖片。因此,我們許多人一直致力於追求最佳化圖片。
Aurora 團隊相信,只要善用架構的強大功能,就能為開發人員常見的挑戰提供內建解決方案。他們第一次涉足圖片最佳化領域,就是使用 Next.js 圖片元件。他們認為這個元件是測試場域,可用來測試改善圖片最佳化開發人員體驗 (DX) 是否能讓更多使用架構的應用程式獲得效能優勢。
Next.js 使用者 Leboncoin 提供的第一組結果令人振奮。Leboncoin 開始使用 next/image
後,LCP 大幅改善 (從 2.4 秒縮短至 1.7 秒)。之後,社群開始採用 next/image
,導致符合 LCP 門檻的 Next.js 來源數量增加。不久之後,其他架構也要求類似功能,其中一個就是 Angular。
因此,Aurora 諮詢了 Angular 和 Nuxt,為這些架構製作圖片元件的原型。Nuxt 圖片元件已於去年發布。我們已發布 Angular 圖片指令 (NgOptimizedImage
),為 Angular 提供圖片最佳化預設值。
商機
Angular 是目前開發人員使用的領先 JavaScript 架構之一。HTTPArchive 在行動裝置上檢索的來源超過 5 萬個都使用了這個套件,且在 NPM 上每週下載次數達 近 300 萬次。
從 Core Web Vitals 分數來看,符合「良好」LCP 門檻的 Angular 來源百分比仍有待改善。在 2022 年 6 月,只有 18.74% 的 Angular 網站在行動裝置上有良好的 LCP。在行動裝置和電腦上,超過 70% 的網頁都會使用圖片做為 LCP 元素,因此未經最佳化的 LCP 圖片,可能是 Angular 網站 LCP 較差的主要原因之一。
Angular 圖片指令旨在協助改善這些數字。
NgOptimizedImage 指令的 MVP
Angular 圖片指令的 MVP 是根據 Aurora 迄今建構的圖片元件所學到的經驗,並將設計調整為符合 Angular 的用戶端算繪體驗。許多標準圖片最佳化問題已透過以下方式解決:
- 提供強大的預設值。
- 擲回錯誤或警告,確保符合最佳做法。
設計重點如下:
智慧延遲載入
使用者在網頁載入時看不到的圖片 (例如下捲圖片或隱藏的輪轉介面圖片),最好採用延遲載入。延後載入可釋出瀏覽器資源,以便載入其他重要文字、媒體或指令碼。大多數圖片都不是必要的,應採用延遲載入功能,但在 2021 年,只有 7.8% 的網頁使用原生延遲載入功能。
Angular 圖片指令預設會延遲載入非重要圖片,並只會立即載入特別標示為
priority
的圖片。這麼做可確保大多數圖片都能以最佳方式載入。優先處理重要圖片
新增資源提示 (例如
preload
或preconnect
) 來優先載入重要圖片,這是建議的最佳做法。不過,大多數應用程式並未使用這些功能。根據 2021 年網路年鑑,只有 12.7% 的行動網頁使用預先連線提示,且只有 22.1% 的行動網頁使用預先載入提示。當圖片標示為優先時,圖片指令會在兩個方面發揮作用。
- 它會將圖片的 fetchpriority 設為
"high"
,讓瀏覽器知道應以高優先順序下載圖片。 - 在開發模式中,執行階段檢查會確認已納入與圖片來源相對應的
preconnect
資源提示。
在開發模式中,指令也會使用 PerformanceObserver API 驗證 LCP 圖片是否已如預期標示為
priority
。如果未標示為priority
,系統會擲回錯誤,指示開發人員將priority
屬性新增至 LCP 圖片。最終,這種自動化和符合性組合可確保 LCP 圖片具有
preconnect
提示、fetchpriority
屬性值為high
,且不會延遲載入。- 它會將圖片的 fetchpriority 設為
針對熱門圖片工具進行最佳化設定
建議 Angular 應用程式使用圖片 CDN,因為這些服務通常會預設提供最佳化服務。
此指令可提供特別吸引人的開發人員體驗 (DX),讓您在應用程式中設定圖片 CDN,鼓勵使用圖片 CDN。此指令支援載入器 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>
都相同 (至少在放送時間)。將任何preload
提示新增至<head>
,表示即使不需要,所有路徑都會預先載入資源。因此,我們不建議手動新增preload
提示。在轉譯期間自動新增:在 CSR 應用程式中,在轉譯期間使用架構在文件標頭新增預先載入提示並無幫助。由於轉譯作業會在下載及執行 JavaScript 後才執行,因此
<head>
會在太晚的時間才轉譯,因此不會有任何價值。對於第一個版本的指令,
preconnect
提示和fetchpriority
提示的組合可用於將圖片優先顯示,而非preload
。不過,Aurora 目前正與 Angular CLI 團隊合作,以便在建構期間自動插入資源提示。敬請期待!在伺服器上最佳化圖片大小和格式
由於 Angular 應用程式通常會在用戶端進行轉譯,因此無法在要求時壓縮檔案系統中的圖片,且會原封不動地提供。基於這個原因,建議您使用圖片 CDN 壓縮圖片,並視需要將圖片轉換為 WebP 等新式格式或 AVIF。
雖然指令不會強制使用圖片 CDN,但強烈建議您搭配指令使用圖片 CDN,並透過內建的載入器確保使用正確的設定選項。
影響
以下示範會說明 Angular 圖片指令可為圖片效能帶來的差異。比較兩個網站:
網站 1:使用原生 <img>
元素,搭配透過 Imgix CDN (搭配預設設定選項) 提供的圖片。
第二個網站:針對所有圖片使用 image 指令。並包含指令擲回的警告或錯誤所直接建議的最佳化項目。
該團隊與合作夥伴合作,驗證圖片指令對實際企業 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/universal) 的圖片最佳化解決方案也相當重要。
改善開發人員體驗
NgOptimizedImage
要求為每張圖片指定width
和height
屬性。不過,針對每張圖片指定這些屬性可能會讓部分開發人員感到疲累。在下一個版本中,我們可能會改善開發人員的使用體驗,如下所示:
結論
從 14.2.0 版的開發人員預覽版開始,開發人員將可分階段使用 Angular 圖片指令。歡迎試用 NgOptimizedImage
,並提供意見回饋!
特別感謝 Katie Hempenius 和 Alex Castle 的貢獻。