【學習圖片】02:關鍵效能問題

前端小智發表於2023-02-20
本文首發於微信公眾號:大遷世界, 我的微信:qq449245884,我會第一時間和你分享前端行業趨勢,學習途徑等等。
更多開源作品請看 GitHub https://github.com/qq449245884/xiaozhi ,包含一線大廠面試完整考點、資料以及我的系列文章。

目前,影像是Web中規模最大的資源,無論是總傳輸大小還是每頁請求數量。截至2022年6月,中位數網頁的總傳輸大小約為2MB,其中影像僅佔近一半。可以說,最佳化影像請求可能是我們可以進行的最大效能最佳化。

推遲影像請求

首先,我們來看一個重要的屬性:loading="lazy":

<img src="image.jpg" loading="lazy" alt="…">

使用這個屬性可能很簡單,但它對效能的影響可以非常有效的:如果影像不出現在視口中,那麼就不會發出請求,並且也不會浪費頻寬。

然而,有一個問題:推遲請求意味著不能利用瀏覽器儘早請求影像。如果在佈局頂部的 img 元素上使用 loading="lazy",因此在頁面首次載入時更有可能出現在使用者的視口中,則這些影像對使用者來說可能顯示得更慢。

優先提示

loading 屬性是Web 標準努力的一個成果,讓開發人員對瀏覽器請求的優先順序更多地控制。

大家可能知道瀏覽器的基本請求優先順序方法:例如,對文件 <head> 中的外部 CSS 檔案的請求會優先執行並阻止渲染,而對於在 </body> 之前的外部 JavaScript 檔案的請求被延遲到渲染完成。如果 <img> 上的 loading 屬性的值是 'lazy',則相關的影像請求將被延遲,直到瀏覽器確定它將顯示給使用者為止。否則,該影像將具有與頁面上任何其他影像相同的優先順序。

實驗性的 fetchpriority 屬性讓開發人員對資源的優先順序更加精細地控制,允許我們相對於同類資源標記資源為 'high''low' 優先順序。

fetchpriority 的使用場景與 loading 屬性相似,但覆蓋面更廣。例如,我們可以僅在使用者互動後顯示的影像上使用 fetchpriority="low"(無論該影像是否在使用者的視口中),以優先處理頁面上的可見影像,或使用 fetchpriority="high" 優先處理我們知道頁面渲染後立即可見的視口。

注意,fetchpriorityloading 不同,它不會從根本上改變瀏覽器的行為。它不會指示瀏覽器在其他資源之前載入某些資源,而是為它對請求資源的決策提供了重要的背景。

衡量影像的影響

在最佳化影像時,對使用者的感知效能通常更為重要,並且比僅僅測量資料傳輸大小更難衡量。

Web Vitals 提供可衡量的、可操作的指標和指導,以提高使用者體驗,突出了諸如網頁伺服器響應時間過慢、渲染問題和互動延遲等問題。核心 Web Vitals 是這些目標的一個子集,專注於使用者對單個頁面的直接體驗——一組技術測量,它們共同決定了體驗對使用者來說有多快。

Cumulative Layout Shift

累積佈局位移(CLS)是視覺穩定性的度量。它是衡量頁面內容佈局在載入資源並渲染頁面時如何移動的指標。任何使用了Web的人都有過因頁面在某個延遲的字型或圖片資源突然渲染而跳動而導致在長文章中的位置丟失的經歷,或者把互動元素移動到指標之外的位置。

CLS高的情況最多隻是一種麻煩,在最壞的情況下是導致使用者錯誤的原因,例如,在使用者單擊時“取消”按鈕移動到先前被“確認”按鈕佔用的位置。

由於載入時間較長以及它們在佈局中所佔的空間,因此影像是導致 CLS分數較高的常見原因。

事例:https://codepen.io/web-dot-de...

由於現代瀏覽器的相對較新的變化,避免因影像導致的高CLS分數比你想象的更容易。如果你已經在前端工作了幾年,對<img>上的widthheight屬性已經很熟悉:在CSS的廣泛採用之前,這是控制影像大小的唯一方法。

<img src="image.jpg" height="200" width="400" alt="…">

這些屬性因為試圖將樣式和標記分離,特別是響應式網頁設計使得透過CSS指定百分比尺寸的必要性,而不再使用。在響應式網頁設計的早期,"刪除未使用的widthheight 屬性"是常見的建議,因為我們在CSS中指定的值,即max-width: 100%height: auto,將覆蓋它們。

<img src="image.jpg" alt="…">
img {
  max-width: 100%;
  height: auto;
}

在以前的情況中,刪除了<img>元素上的heightwidth屬性後,瀏覽器確定影像高度的唯一方法是請求源、解析它並在其固有的比例渲染它,基於樣式表應用後在佈局中佔據的寬度。這個過程的大部分在頁面渲染後才完成,新計算出的高度導致了其他佈局的移動。

從2019年開始,瀏覽器行為被更新以不同的方式處理widthheight屬性。這些屬性不再用於確定img元素在佈局中的固定、畫素為基礎的大小,而是可以認為代表影像的長寬比,語法相同。現代瀏覽器會在頁面渲染前將這些值除以對方,以確定img元素的內在長寬比,從而允許它在佈局渲染時保留影像佔據的空間。

作為一項規則,我們應該始終在<img>上使用heightwidth屬性,其值應與影像源的內在大小匹配,只要我們確保指定了height:automax-width:100%,以覆蓋HTML屬性中的高度即可。

<img src="image.jpg" height="200" width="400" alt="…">
img {
  max-width: 100%;
  height: auto;
}

透過在 <img>元素上使用 widthheight 屬性,將避免因影像而導致的CLS高分。

事例:https://codepen.io/web-dot-de...

重要的是,這種方法沒有任何缺點,因為它依賴於長期存在的瀏覽器行為,任何支援基本CSS的瀏覽器都將像往常一樣工作,HTML屬性中的 heightwidth 屬性將被樣式覆蓋。

雖然 widthheight屬性透過保留影像所需的佈局空間來避免CLS問題,但會向使用者渲染空白或低質量的佔位符,等待影像傳輸和黨建也不理想。儘管可以採取一些措施減少載入慢的影像的可測量和可察覺影響,但向使用者更快地黨建完整影像的唯一方法是透過減小傳輸大小。

Largest Contentful Paint

最大內容繪製(LCP)衡量使用者可視視口中最大“內容繪製”元素渲染所需的時間,即佔可見頁面最大百分比的內容元素。在表面上,這個指標似乎過於具體,但它實際上代表了從使用者的角度看到頁面大部分內容已被渲染的時間。 LCP是(感知的)效能的關鍵指標

DOMContentLoadedwindow.onload事件等指標可以用於確定當前頁面載入的過程在技術上已完成,但它們不一定對應於使用者對頁面的體驗。在使用者視野外的元素的渲染略有延遲,將被計入這些指標中,但可能完全被現實世界的使用者忽略。長LCP意味著使用者對頁面的第一印象是頁面緩慢或徹底停滯。

使用者對 LCP 的感知對使用者體驗產生直接影響。去年 Vodafone 進行的一項實驗發現,LCP 提高 31% 不僅導致銷售額增加了 8%,這本身就是一個很好的結果,但他們的總使用者中,潛在客戶數量增加了 15%,訪問購物車的使用者數量增加了 11%

70% 以上的網頁中,初始視口中的最大元素涉及影像,可以是單獨的 <img> 元素,也可以是具有背景影像的元素。換句話說,70% 的頁面的 LCP 分數都是基於影像效能。不難想象,大而引人注目的影像和標誌很可能會在“above the fold”被找到。

image.png

我們可以採取一些步驟來避免 LCP 延遲:首先,不要在above the fold 影像上指定 loading="lazy",因為延遲請求直到頁面渲染完成將可能對 LCP 分數產生巨大的負面影響。其次,使用 fetchpriority="high" 可以告訴瀏覽器該影像的傳輸應該優先於頁面上的其他影像。

牢記這些規則,提高頁面 LCP 分數的最重要的事情是減少傳輸和渲染這些影像所需的時間。為了實現這一目標,您要保持影像源儘可能小和高效(當然不會犧牲質量),並確保使用者僅獲取對他們的瀏覽上下文最有意義的影像資源。

總結

影像資源是對使用者頻寬的最大流失,這是從傳輸每個渲染頁面所必需的其他資源所消耗的頻寬。影像在效能感知方面引入了重要問題,無論是在周圍頁面佈局渲染後還是之前。簡而言之:影像資源造成了損害。

儘管如此令人生畏,但是“如果影像少一些,Web的效能就會更好”肯定是僅僅從效能角度來說是正確的,但它也對使用者造成了巨大的不利影響。影像是Web的重要組成部分,我們不應該僅為了效能而妥協有意義的內容的質量。

程式碼部署後可能存在的BUG沒法實時知道,事後為了解決這些BUG,花了大量的時間進行log 除錯,這邊順便給大家推薦一個好用的BUG監控工具 Fundebug

原文:https://web.dev/learn/images/...

交流

有夢想,有乾貨,微信搜尋 【大遷世界】 關注這個在凌晨還在刷碗的刷碗智。

本文 GitHub https://github.com/qq449245884/xiaozhi 已收錄,有一線大廠面試完整考點、資料以及我的系列文章。

相關文章