2022 年 5 月,Aurora 和 Angular 團隊宣布將合作為 Angular 開發圖片指令。這項指令最近已在 Angular 第 14.2 版中發布開發人員預覽版。本文將說明新的圖片指令 NgOptimizedImage
如何支援 Angular 中的圖片最佳化功能。
背景
圖片是網路使用者體驗中常見且重要的元素,99.9% 的網頁都會產生一或多個圖片的要求。圖片也是影響網頁重量的最大因素,每個網頁的平均大小為 982 千位元組。
由於圖片的數量和大小不斷增加,可能會影響網頁效能,並影響網站體驗核心指標指標。在 79.4% 的電腦版網頁中,圖片是 2021 年最大的內容繪製 (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 的貢獻。