- 原文地址:A Deep Dive into Native Lazy-Loading for Images and Frames
- 原文做者:Erk Struwe
- 譯文出自:掘金翻譯計劃
- 本文永久連接:github.com/xitu/gold-m…
- 譯者:Baddyo
- 校對者:Mcskiller
當今的網站上充斥着大量媒體資源,例如圖片和視頻。圖片約佔網站平均通訊量的 50%。然而這些圖片中的大部分都沒機會進入用戶的視野,由於它們位於網站頁面的頭版以外。javascript
看到本文標題你會問「懶加載是什麼東西?」CSS-Tricks 網站中有很是多的探討懶加載的文章,其中有一篇很是詳盡的《用 JavaScript 花式實現懶加載的指南文檔》。簡言之,咱們要討論的是一種延遲網絡資源加載的機制,在該機制下,網頁內容按需加載,或者說得更直白些,當網頁內容進入用戶視野時再觸發加載。css
這樣作有什麼好處?壓縮初始頁面的體積以提高加載速度;免於爲用戶根本不會看到的內容浪費網絡請求。html
若是你以前讀過關於懶加載的其餘文章,你就會明白,咱們必須藉助各類不一樣的方式才能實現懶加載功能。而當原生 HTML 用 loading
特性支持懶加載功能後,那可就柳暗花明又一村了。目前僅有 Chrome 支持 loading
特性,但有望全面開花。Chrome 近期正在開發和測試對原生懶加載特性的支持功能,預計在 2019 年 9 月初發布的 Chrome 77 版本中面世。前端
截至目前,咱們這羣開發者仍須要用 JavaScript(不管是藉助第三方庫仍是本身從零手寫)實現懶加載功能。大多數懶加載庫的原理都是:java
src
特性的 img
元素,這樣瀏覽器就不會加載任何數據。而圖片的連接地址放在 img
元素的其餘特性上,例如 data-src
。<img data-src="https://tiny.pictures/example1.jpg" alt="...">
複製代碼
<script src="LazyLoadingLibrary.js"></script>
<script>LazyLoadingLibrary.run()</script>
複製代碼
data-src
特性的值賦給本來爲空的 src
特性。<img src="https://tiny.pictures/example1.jpg" data-src="https://tiny.pictures/example1.jpg" alt="...">
複製代碼
長期以來,咱們都在用這種方式實現懶加載。但這並非理想的實現方式。android
該方式的顯著問題就是,要展現網站頁面,得通過好幾個關鍵步驟。總共要三個步驟,還必須得按順序執行:ios
若是把這樣的懶加載技術應用到頭版中的圖片上,頁面在加載期間會發生閃爍,由於一開始繪製的時候,頁面中沒有圖片(閃爍發生於第 1 步仍是第 2 步以後,取決於載入庫的腳本用的是 defer
仍是 async
),懶加載庫生效後,圖片才姍姍來遲。這還會給用戶形成網頁加載速度緩慢的錯覺。git
另外,懶加載庫自己也是對帶寬和 CPU 算力的佔用。並且別忘了,若是用戶禁用了 JavaScript(都已經2019年了,這種狀況咱們不予考慮,你說對吧?),那麼懶加載庫是行不通的。github
哦對了,那些依賴 RSS 來發布內容的網站(如 CSS-Tricks)又該怎麼辦呢?若是初始的頁面中不載入圖片,那麼 RSS 版本的頁面就始終不會顯示圖片。web
凡此種種,不一而足。
如前文所說,Chromium 開發團隊和 Google Chrome 開發團隊從 Chrome 75 開始,裝載 loading
特性支持的原生懶加載功能。關於該特性及其值,咱們稍後再討論,仍是先在瀏覽器裏啓用這個功能來一探究竟吧。
從 Chrome 75 開始,咱們能夠切換兩個開關來手動啓用懶加載功能。預計從 Chrome 77(計劃於 2019 年 9 月發佈)開始,該功能就會是默認開啓的了。
chrome://flags
。lazy
。↑↑↑ 示意圖:Google Chrome 中的原生懶加載功能開關 ↑↑↑
打開 JavaScript 控制檯(按 F12
鍵),看看懶加載功能是否已經成功激活。若是成功激活,你會看到以下警告信息:
[Intervention] Images loaded lazily and replaced with placeholders. Load events are deferred.(圖片以懶惰方式加載並替換爲佔位符。加載事件被延遲。)
都搞定了嗎?那就一塊兒深刻了解 loading
吧。
img
和 iframe
元素都支持 loading
特性。切記,loading
特性的值不是讓瀏覽器嚴格執行的命令,而是幫助瀏覽器本身決定是否要懶加載圖片或者框架。
下面會介紹 loading
特性可取的三個值。在下文中的每張圖片下面,你均可以看到一張表格,其中列着每一個圖片資源的加載時序。範圍請求(譯者注:原文用詞爲 Range response,疑似筆誤)指的是一種預檢圖片局部的請求,用來肯定圖片文件的大小(參見詳細原理)。若是該列有內容,證實瀏覽器成功發出了範圍請求。
請注意 startTime 列,該列代表了在 DOM 解析後,圖片的加載被推遲了多長時間。你可使用強制刷新(CTRL + Shift + R)從新觸發範圍請求。
auto
<img src="auto-cat.jpg" loading="auto" alt="...">
<img src="auto-cat.jpg" alt="...">
<iframe src="https://css-tricks.com/" loading="auto"></iframe>
<iframe src="https://css-tricks.com/"></iframe>
複製代碼
↑↑↑ 示意圖:自動加載的車模照 ↑↑↑
度量 / 請求 | #1 |
---|---|
encodedBodySize | 20718 bytes |
decodedBodySize | 20718 bytes |
transferSize | 0 bytes |
startTime | 54 ms |
requestStart | 592 ms |
responseStart | 596 ms |
responseEnd | 601 ms |
timeToFirstByte | 4 ms |
downloadDuration | 5 ms |
把 loading
設爲 auto
(或者將其置空:loading=""
),可讓瀏覽器本身決定是否懶加載圖片。決定是否懶加載要考慮不少因素,例如平臺、是否處於 Data Saver 模式(譯者注:Chrome 已於 2019 年 5 月 6 日廢棄了該功能)、網絡情況、圖片大小、是圖片仍是 iframe 以及 CSS 的 display
屬性等等。(關於考慮這些因素的緣由,參見此處。)
eager
<img src="auto-cat.jpg" loading="eager" alt="...">
<iframe src="https://css-tricks.com/" loading="eager"></iframe>
複製代碼
↑↑↑ 示意圖:急切加載的急豹圖 ↑↑↑
度量 / 請求 | #1 |
---|---|
encodedBodySize | 24019 bytes |
decodedBodySize | 24019 bytes |
transferSize | 0 bytes |
startTime | 54 ms |
requestStart | 592 ms |
responseStart | 600 ms |
responseEnd | 605 ms |
timeToFirstByte | 7 ms |
downloadDuration | 5 ms |
eager
告訴瀏覽器這張圖片須要當即加載。若是加載已經被延遲了(好比初始值爲 lazy
,後來用 JavaScript 改爲了eager
),那麼瀏覽器也應該當即加載圖片。
lazy
<img src="auto-cat.jpg" loading="lazy" alt="...">
<iframe src="https://css-tricks.com/" loading="lazy"></iframe>
複製代碼
↑↑↑ 示意圖:懶加載的懶貓圖 ↑↑↑
度量 / 請求 | #1 |
---|---|
encodedBodySize | 12112 bytes |
decodedBodySize | 12112 bytes |
transferSize | 0 bytes |
startTime | 54 ms |
requestStart | 593 ms |
responseStart | 599 ms |
responseEnd | 604 ms |
timeToFirstByte | 6 ms |
downloadDuration | 5 ms |
lazy
告訴瀏覽器此圖片應該懶加載。懶加載到底有多「懶」,這應該由瀏覽器來解釋,而說明文檔代表,懶加載始於用戶將頁面滾動到圖片附近之時,意即當圖片即將進入視野時加載。
loading
特性的原理與基於 JavaScript 的懶加載庫不一樣,原生懶加載功能使用了一種預檢請求來獲取圖片文件的前 2048 字節數據。根據預先取得的數據,瀏覽器會試着肯定該圖片的大小,便於在完整圖片的位置插入一個隱形的佔位符,防止加載過程當中頁面發生閃爍現象。
在第一個(若是圖片大小小於 2 KB,一個預檢請求就夠了)或第二個請求完成後,完整圖片一加載完畢,其 load
事件就會解除監聽。請注意,若是沒有完成第二個請求,那麼load
事件可能會一直綁定着。
從今之後,瀏覽器因獲取圖片而發出的請求的數量可能會翻倍。每張圖片對應兩個請求:先是範圍請求,再是完整請求。要確保你的服務器支持 HTTP
Range: 0-2047
請求頭,而響應狀態碼要用206(部份內容)
,防止整個圖片被傳送兩次。
每一個用戶都會發送大量的後續請求,所以 Web 服務器對 HTTP/2 協議的支持變得愈來愈重要。
如今咱們來聊聊延遲的內容。Chrome 瀏覽器的渲染引擎 Blink 採用啓發式技術來肯定哪些內容應該延遲加載、延遲多久。Scott Little 在他的設計文檔中全面地列出了肯定延遲策略的條件。下面是肯定延遲對象的簡短策略:
全部平臺中設置了 loading="lazy"
的圖片和框架
瀏覽器爲 Android 系統中的 Chrome,啓用了 Data Saver 模式;而且知足下列條件的圖片:
loading="auto"
或 loading=""
width
和 height
特性的值都不小於 10 px知足下列條件的框架:
loading="auto"
或 loading=""
display: none
或 visibility: hidden
(防止將跟蹤框架一併延遲加載)srcset
特性的響應式圖片對於帶有 srcset
特性的響應式圖片,原生懶加載一樣有效。srcset
特性提供了一系列圖片文件供瀏覽器選用。根據用戶的屏幕尺寸、設備像素比、網絡情況等因素,瀏覽器會選取最適合情境的圖片。像 tiny.pictures 這樣的圖片優化 CDN 能夠實時提供備選圖片,無需後端開發。
<img src="https://demo.tiny.pictures/native-lazy-loading/lazy-cat.jpg" srcset="https://demo.tiny.pictures/native-lazy-loading/lazy-cat.jpg?width=400 400w, https://demo.tiny.pictures/native-lazy-loading/lazy-cat.jpg?width=800 800w" loading="lazy" alt="...">
複製代碼
在撰寫本文時,尚未瀏覽器默認支持原生懶加載功能。但就像以前說的,Chrome 從 77 版本開始會默認開啓懶加載。除此以外,目前尚未瀏覽器廠商宣稱支持該功能。(Edge 將是個例外,由於它即將轉爲 Chromium 內核。)
你能夠用幾行 JavaScript 代碼檢查支持狀況:
if ("loading" in HTMLImageElement.prototype) {
// 支持。
} else {
// 不支持。你可能須要引入懶加載庫(下文已列出)。
}
複製代碼
參見 CodePen 中 Erk Struwe(@erkstruwe)的代碼示例:瀏覽器原生懶加載支持探測器
多數基於 JavaScript 的懶加載庫都有一個炫酷的功能:模糊佔位圖片(LQIP)。該功能基本上利用了這個原理:即便後來 src
特性的值會被另外的 URL 替換掉,瀏覽器仍是會在一開始就馬上加載 img
元素。這樣,咱們能夠在頁面載入時先加載一個不清晰的小圖片,以後再用完整圖片代替它。
如今咱們能夠利用這個功能,在不支持懶加載的瀏覽器中模擬原生懶加載的 2 KB 範圍請求,以期實現模糊佔位圖片相同的效果。
參見 CodePen 中 Erk Struwe(@erkstruwe)的代碼示例:針對原生懶加載的 JavaScript 回退方案,以及模糊佔位圖片功能
這個新功能着實讓我激動。原生懶加載功能的發佈近在眼前,會對全球互聯網通訊產生非凡影響。就算它只能改變啓發式技術的一小部分,老實說我仍不明白爲什麼人們不給予足夠的關注。
想一想吧,隨着在不一樣的 Chrome 平臺中逐漸推廣、auto
值成爲默認選項,世界上最流行的瀏覽器即將對視口外的圖片和框架應用懶加載技術。決堤般的通訊量會大面積擊潰那些健壯性不足的網站,並且,蜂擁而至的圖片探測請求也會傷及網絡服務器。
接下來遭殃的就是追蹤技術: 假設那些深受信賴的追蹤像素和追蹤框架都沒法加載,那麼數據分析領域及其周邊產業將面臨被動局面。咱們只能但願他們千萬別惶恐不安,千萬別給每一個圖片都加上 loading="eager"
這項偉大功能,這樣添加 loading
特性根本不是爲了服務網站用戶,實在暴殄天物。他們更應該改寫代碼,以便於被啓發式技術識別爲追蹤像素。
Web 開發者、數據分析經理和運營經理應該當即檢查本身的網站,確保前端支持原生懶加載、後端支持範圍請求和 HTTP/2 協議。
萬一原生懶加載功能出現問題,或者你想把圖片加載優化到極致(包括自動支持 WebP、模糊佔位圖片等等),圖片優化 CDN 能助你一臂之力。更多內容參見 tiny.pictures!
若是發現譯文存在錯誤或其餘須要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改並 PR,也可得到相應獎勵積分。文章開頭的 本文永久連接 即爲本文在 GitHub 上的 MarkDown 連接。
掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 Android、iOS、前端、後端、區塊鏈、產品、設計、人工智能等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃、官方微博、知乎專欄。