現代圖片性能優化及體驗優化指南 - 懶載入及非同步圖像解碼方案

来源:https://www.cnblogs.com/coco1s/archive/2023/02/28/17162742.html
-Advertisement-
Play Games

本文是系列第四篇。系列文章: 現代圖片性能優化及體驗優化指南 - 圖片類型及 Picture 標簽的使用 現代圖片性能優化及體驗優化指南 - 響應式圖片方案 現代圖片性能優化及體驗優化指南 - # 縮放精細化展示及避免佈局偏移、拉伸 圖片資源,在我們的業務中可謂是占據了非常大頭的一環,尤其是其對帶寬 ...


本文是系列第四篇。系列文章:

  1. 現代圖片性能優化及體驗優化指南 - 圖片類型及 Picture 標簽的使用
  2. 現代圖片性能優化及體驗優化指南 - 響應式圖片方案
  3. 現代圖片性能優化及體驗優化指南 - # 縮放精細化展示及避免佈局偏移、拉伸

圖片資源,在我們的業務中可謂是占據了非常大頭的一環,尤其是其對帶寬的消耗是十分巨大的。

對圖片的性能優化及體驗優化在今天就顯得尤為重要。本文,就將從各個方面闡述,在各種新特性滿頭飛的今天,我們可以如何儘可能的對我們的圖片資源,進行性能優化及體驗優化。

懶載入/非同步圖像解碼方案

繼續下一個章節。本章節,我們來討論下圖片的懶載入與非同步圖像解碼方案。

圖片的懶載入

懶載入是一種網頁性能優化的常見方式,它能極大的提升用戶體驗。到今天,現在一張圖片超過幾 M 已經是常見事了。如果每次進入頁面都需要請求頁面上的所有的圖片資源,會較大的影響用戶體驗,對用戶的帶寬也是一種極大的損耗。

所以,圖片懶載入的意義即是,當頁面未滾動到相應區域,該區域內的圖片資源(網路請求)不會被載入。反之,當頁面滾動到相應區域,相關圖片資源的請求才會被髮起。

在過去,我們通常都是使用 JavaScript 方案進行圖片的懶載入。而今天,我們在圖片的懶載入實現上,有了更多不一樣的選擇。

JavaScript 方案實現圖片的懶載入

首先,回顧一下過往最常見的,使用 JavaScript 方案實現圖片的懶載入。

通過 JavaScript 實現的懶載入,主要是兩種方式:

  1. 監聽 onscroll 事件,通過 getBoundingClientRect API 獲取元素圖片距離視口頂部的距離,配合當前可視區域的位置實現圖片的懶載入
  2. 通過 HTML5 的 IntersectionObserver API,Intersection Observer(交叉觀察器) 配合監聽元素的 isIntersecting 屬性,判斷元素是否在可視區內,能夠實現比監聽 onscroll 性能更佳的圖片懶載入方案

但是,JavaScript 方案的一個劣勢在於,不管如何,需要引入一定量的 JavaScript 代碼,進行一定量的運算。

到今天,其實我們有更多的其他便捷的方式去實現圖片的懶載入。

使用 content-visibility: auto 實現圖片內容的延遲渲染

首先,介紹一個非常有用,但是相對較為冷門的屬性 -- content-visibility

content-visibility:屬性控制一個元素是否渲染其內容,它允許用戶代理(瀏覽器)潛在地省略大量佈局和渲染工作,直到需要它為止。

利用 content-visibility 的特性,我們可以實現如果該元素當前不在屏幕上,則不會渲染其後代元素

假設我們有這樣一個 DEMO:

<div class="g-wrap">
    // 模塊 1
    <div class="paragraph">
        <p>Lorem Start!</p>   
        <img src="https://s1.ax1x.com/2023/02/20/pSX1xMV.png" alt="" />
        <p>Lorem End!</p>  
    </div>
    // 模塊 2
    <div class="paragraph">
        <p>Lorem Start!</p>   
        <img src="https://s1.ax1x.com/2023/02/20/pSX1xMV.png" alt="" />
        <p>Lorem End!</p>  
    </div>
    // ... 連續幾十個上述類似的結構
</div>

只需要給需要延遲(實時)渲染的元素,設置簡單的 CSS 樣式:

.paragraph {
    content-visibility: auto;
}

我們來看一下,設置了 content-visibility: auto 與沒設置的區別。

如果,不添加上述的 content-visibility: auto 代碼,頁面的滾動條及滾動效果如下:

那麼,在添加了 content-visibility: auto 之後,註意觀察頁面的滾動條及滾動效果:

可以看到滾動條在向下滾動在不斷的抽搐,這是由於下麵不在可視區域內的內容,一開始是沒有被渲染的,在每次滾動的過程中,才逐漸渲染,以此來提升性能。

Codepen Deom -- content-visibility: auto Image Load Demo

content-visibility: auto VS 圖片懶載入

當然,其實使用 content-visibility: auto 並不能真正意義上實現圖片的懶載入。

這是因為,即便當前頁面可視區域外的內容未被渲染,但是圖片資源的 HTTP/HTTPS 請求,依然會在頁面一開始被觸發!

因此,這也得到了一個非常重要的結論:

content-visibility: auto 無法直接替代圖片懶載入,設置了 content-visibility: auto 的元素在可視區外只是未被渲染,但是其中的靜態資源仍舊會在頁面初始化的時候被全部載入。因此,它更像是一個虛擬列表的替代方案。

關於 content-visibility 本文限於篇幅,沒有完全展開,但是它是一個非常有意思且對渲染性能有幫助的屬性,完整的教程,你可以看我的這篇文章 -- 使用 content-visibility 優化渲染性能

使用 loading=lazy HTML 屬性實現圖片懶載入

OK,content-visibility 很不錯,但是略有瑕疵。但是,我們還有其他方式。

HTML5 新增了一個 loading 屬性。

到今天,除了 IE 系列瀏覽器,目前都支持通過 loading 屬性實現延遲載入。此屬性可以添加到 <img> 元素中,也可以添加到 <iframe> 元素中。

屬性的值為 loading=lazy 會告訴瀏覽器,如果圖像位於可視區時,則立即載入圖像,併在用戶滾動到它們附近時獲取其他圖像。

我們可以像是這樣使用它:

<img src="xxx.png" loading="lazy">

這樣,便可以非常便捷的實現圖片的懶載入,省去了添加繁瑣的 JavaScript 代碼的過程

看看 loading=lazy 到今天(2023-02-26)的相容性,還是非常不錯的:

使用 decoding=async 實現圖片的非同步解碼

除了 loading=lazy,HTML5 還新增了一個非常有意思的屬性增強圖片的用戶體驗。那就是 decoding 屬性。

HTMLImageElement 介面的 decoding 屬性用於告訴瀏覽器使用何種方式解析圖像數據。

它的可選取值如下:

  • sync: 同步解碼圖像,保證與其他內容一起顯示。
  • async: 非同步解碼圖像,加快顯示其他內容。
  • auto: 預設模式,表示不偏好解碼模式。由瀏覽器決定哪種方式更適合用戶。

上文其實也提及了,瀏覽器在進行圖片渲染展示的過程中,是需要對圖片文件進行解碼的,這一個過程快慢與圖片格式有關。

而如果我們不希望圖片的渲染解碼影響頁面的其他內容的展示,可以使用 decoding=async 選項,像是這樣:

<img src="xxx.png" decoding="async">

這樣,瀏覽器便會非同步解碼圖像,加快顯示其他內容。這是圖片優化方案中可選的一環。

同樣的,我們來看看到今天(2023-02-26),decoding="async" 的相容性,整體還是非常不錯的,作為漸進增強方案使用,是非常好的選擇。

實際檢驗 loading=lazydecoding=async 效果

OK,下麵我們製作一個簡單的 DEMO,試一下 loading=lazydecoding=async 的效果。

我們準備一個擁有 339 個圖片的 HTML 頁面,每個圖片文件的 src 大小不一。

<div class="g-container">
    <img src="image1.jpeg">
    <img src="image2.jpeg">
    // ... 339 個
</div>

CSS 的設置也很重要,由於是純圖片頁面,如果不給圖片設置預設高寬,最頁面刷新的一瞬間,<img> 元素的高寬都是 0,會導致所有 <img> 元素都在可視區內,所以,我們需要給 <img> 設置一個預設的高寬:

img {
    margin: 8px;
    width: 300px;
    height: 200px;
    object-fit: cover;
}

這樣,再不添加 loading=lazydecoding=async 的狀態下,看看 Network 的表現:

我這裡沒有模擬弱網環境,網速非常快,可以看到,發送了 339 個圖片資源請求,也就是全部的圖片資源在頁面載入的過程中都請求了,頁面 Load 事件完成的時間為 1.28s。

好,我們給所有的圖片元素,添加上 loading=lazydecoding=async

<div class="g-container">
    <img src="image1.jpeg" loading="lazy" decoding="async">
    <img src="image2.jpeg" loading="lazy" decoding="async">
    // ... 339 個
</div>

看看效果:

可以看到,這一次只發送了 17 個圖片資源請求,頁面 Load 事件完成的時間為 26ms。

優化前 優化後
1.28s 26 ms

1.28s 到 26ms,效果是非常明顯的,如果是弱網環境,對首屏載入性能的提升,會更為明顯

當然,實際我測試的過程也,也單獨試過 decoding="async" 的作用,只是由於是純圖片頁面,效果不那麼明顯。感興趣的同學,可以自行嘗試。

總結一下

在本章節中,我們介紹了不同的方式實現圖片的懶載入、延遲渲染、非同步解碼,它們分別是:

  1. 通過 onscroll 事件與 getBoundingClientRect API 實現圖片的懶載入方案
  2. 通過 Intersection Observer(交叉觀察器)實現比監聽 onscroll 性能更佳的圖片懶載入方案
  3. 通過 content-visibility: auto 實現圖片資源的延遲渲染
  4. 通過 loading=lazy HTML 屬性實現圖片懶載入
  5. 通過 decoding=async HTML 屬性實現圖片的非同步解碼

當然,本文是現代圖片性能優化及體驗優化指南的第四篇,後續將給大家帶來圖片優化的最後一個章節:

  • 可訪問性 & 圖片資源的容錯及錯誤處理

感興趣的可以提前關註。

最後

OK,本文到此結束,希望本文對你有所幫助

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 如果希望自己的代碼更優雅、可維護性更高以及更簡潔,往往離不開設計模式這一解決方案。 在JS設計模式中,最核心的思想:封裝變化(將變與不變分離,確保變化的部分靈活,不變的部分穩定)。 單例模式 那麼來說說第一個常見的設計模式:單例模式。 單例模式保證一個類僅有一個實例,並提供一個訪問它的全局訪問方式, ...
  • 隨著項目的不斷維護,代碼越來越多,項目越來越大,決定將老項目遷移至vite。本文介紹了Vue老項目像Vite遷移的過程、遇到的問題以及經驗總結。 ...
  • 這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 背景 最近新接手了一批項目,還沒來得及接新需求,一大堆bug就接踵而至,仔細一看,應該返回數組的欄位返回了 null,或者沒有返回,甚至返回了字元串 "null"??? 這我能忍?我立刻截圖發到群里,用紅框加大加粗重點標出。後端同學也積極 ...
  • 這篇要討論的這個概念,應該也不是我發明的新詞,叫 URL 與狀態的雙向綁定,字面意思來說,在刷新頁面或跳轉頁面時解析 URL 並對應更新組件的狀態,在組件狀態更新時同步更新 URL,為什麼要引入這種機制嘞? ...
  • 按照官網初始化nuxt3項目時: 輸入命令 npx nuxi init nuxt3demo 發現會失敗報錯: getaddrinfo ENOENT raw.githubusercontent.com 報錯 解決方案: 手動clone代碼 git clone -b v3 https://github. ...
  • CSS中的BFC、IFC、GFC和FFC是佈局模型中的概念,用於描述元素在文檔流中的佈局行為。它們分別代表塊級格式化上下文(Block Formatting Context)、內聯級格式化上下文(Inline Formatting Context)、網格格式化上下文(Grid Formatting ...
  • tips:如果本文對你有用,請愛心點個贊,提高排名,讓這篇文章幫助更多的人。謝謝大家!比心❤~ 如果解決不了,可以在文末加我微信,進群交流一起學習探討。 背景 項目的要求需要實現規範化,針對項目內所有的滾動條做優化,需要按照UE調整實現:滾動時出現滾動條,停留三秒後,自動消失 由於是就項目的優化,所 ...
  • 我們是袋鼠雲數棧 UED 團隊,致力於打造優秀的一站式數據中台產品。我們始終保持工匠精神,探索前端道路,為社區積累並傳播經驗價值。 前言 數棧作為雲原⽣⼀站式⼤數據開發平臺,從2016年發佈第⼀個版本開始,數棧就始終堅持著以技術為 核⼼、安全為底線、提效為⽬標、中台為戰略的思想,堅定不移地⾛國產化信 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...