web 原生圖片延遲加載

前言

這篇文章中,咱們將看一下新的 loading 屬性,它將原生 <img><iframe> 延遲加載到網頁上!對好奇的人來講,這裏有一個實際的預覽:javascript

<img src="celebration.jpg" loading="lazy" alt="..." />
<iframe src="video-player.html" loading="lazy"></iframe>
複製代碼

咱們但願在 Chrome 75 中提供 loading 支持並深刻研究這個功能,不久以後發佈。在那以前,讓咱們深刻挖掘 loading 是怎麼做用的。html

1、介紹

瀏覽器頁面常常包含大量圖片,這會致使網絡數據使用、頁面膨脹和頁面加載速度等問題。這些圖片大多處於屏幕以外,須要用戶滾動頁面才能看到。java

準確的說,爲了限制屏幕以外的圖片對頁面加載速度的影響,開發者須要用 JavaScript 包(例如 LazySizes)去延遲抓取這些屏幕以外的圖片數據直至用戶滾動靠近。git

一個頁面加載 211 張圖片,沒有延遲加載的例子抓取了 10MB 的圖片數據。延遲加載的版本(使用 LazySizes)只先加載了 250KB 圖片數據,其它圖片等用戶滾動接近時纔會抓取。github

若是瀏覽器能夠爲你避免加載屏幕以外的圖片?這會幫助視野裏的內容加載得更快,減小總體網絡數據使用,減小低端設備內存使用。我很高興去分享很快會成爲可能的 images 和 iframes 新屬性 loadingweb

2、loading 屬性

loading 屬性容許一個瀏覽器去延遲加載屏幕以外的 images 和 iframes 直到用戶滾動靠近。loading 支持三種值:ajax

  • lazy:延遲加載。
  • eager:馬上加載。
  • auto:瀏覽器會決定是不是延遲加載。

不聲明這個屬性至關於設置 loading=autochrome

<img><iframe> 標籤的 loading 屬性正在做爲瀏覽器標準的一部分被處理。瀏覽器

(一)例子

loading 屬性做用於 <img> 標籤(至關於 srcset<picture>)和 <iframe> 標籤。bash

<!-- Lazy-load an offscreen image when the user scrolls near it -->
<img src="unicorn.jpg" loading="lazy" alt=".."/>

<!-- Load an image right away instead of lazy-loading -->
<img src="unicorn.jpg" loading="eager" alt=".."/>

<!-- Browser decides whether or not to lazy-load the image -->
<img src="unicorn.jpg" loading="auto" alt=".."/>

<!-- Lazy-load images in <picture>. <img> is the one driving image loading so <picture> and srcset fall off of that -->
<picture>
  <source media="(min-width: 40em)" srcset="big.jpg 1x, big-hd.jpg 2x">
  <source srcset="small.jpg 1x, small-hd.jpg 2x">
  <img src="fallback.jpg" loading="lazy">
</picture>

<!-- Lazy-load an image that has srcset specified -->
<img src="small.jpg" srcset="large.jpg 1024w, medium.jpg 640w, small.jpg 320w" sizes="(min-width: 36em) 33.3vw, 100vw" alt="A rad wolf" loading="lazy">

<!-- Lazy-load an offscreen iframe when the user scrolls near it -->
<iframe src="video-player.html" loading="lazy"></iframe>
複製代碼

「用戶滾動到附近時」的確切啓發方式留給瀏覽器。通常來講,咱們的但願是在進入視野以前瀏覽器開始提取延遲加載的 images 和 iframes。這將增長圖像或 iframe 在用戶滾動到它們時完成加載的更改。

提示:我建議咱們將其命名爲 loading 屬性,由於它的命名相似於 decoding 屬性。之前的提議,相似於 lazyload 沒法歸納咱們須要支持的多個屬性值(lazyeagerauto)。

3、功能檢測

咱們一直在考慮可以爲延遲加載提供抓取和應用 JavaScript 庫的重要性。支持以下對 loading 的功能檢測:

<script> if ('loading' in HTMLImageElement.prototype) { // Browser supports `loading`.. } else { // Fetch and apply a polyfill/JavaScript library // for lazy-loading instead. } </script>
複製代碼

提示:您還能將 loading 用做漸進加強。支持這個屬性的瀏覽器能根據 loading=lazy 獲取最新延遲加載的行爲,而不支持該屬性的瀏覽器仍然會加載圖片。

(一)跨瀏覽器圖片延遲加載

若是對延遲加載的跨瀏覽器支持很重要,那麼若是你在標記中使用 <img src="unicorn.png" loading="lazy" />,光是對功能檢測和延遲加載庫是不夠的。

標記中須要使用一些例如 <img data-src=unicorn.png />(而不是 src, srcset 或者 <source>)去避免觸發不支持新屬性的瀏覽器的馬上加載。JavaScript 能夠根據是否支持 loading 和加載庫更改成正確的屬性。你能夠認爲這是一個混合延遲加載。

下面一個是混合延遲加載的例子。

  • In-viewport / above-the-fold 圖片是常見 <img> 標籤。data-src 屬性將會破壞預先加載掃描程序,因此咱們想要避免它出如今視野區域的任何內容中。
  • 咱們在 images 上使用 data-src 屬性去避免不支持延遲加載的瀏覽器馬上加載圖片。若是支持 loading,咱們將 data-src 替換成 src。
  • 若是 loading 不被支持,咱們加載一個回調函數(LazySizes)而且初始化。這裏,咱們使用 class=lazyload 代表 LazySizes 圖片咱們想要延遲加載。
<!-- Let's load this in-viewport image normally -->
<img src="hero.jpg" alt=".."/>

<!-- Let's lazy-load the rest of these images -->
<img data-src="unicorn.jpg" loading="lazy" alt=".." class="lazyload"/>
<img data-src="cats.jpg" loading="lazy" alt=".." class="lazyload"/>
<img data-src="dogs.jpg" loading="lazy" alt=".." class="lazyload"/>

<script> if ('loading' in HTMLImageElement.prototype) { const images = document.querySelectorAll("img.lazyload"); images.forEach(img => img.src = img.dataset.src); } else { // Dynamically import the LazySizes library let script = document.createElement("script"); script.async = true; script.src = "https://cdnjs.cloudflare.com/ajax/libs/lazysizes/4.1.8/lazysizes.min.js"; document.body.appendChild(script); } </script>
複製代碼

如下是上述的替代寫法,依賴於動態導入來執行相同的回退庫的抓取。

<!-- Let's load this in-viewport image normally -->
<img src="hero.jpg" alt=".."/>

<!-- Let's lazy-load the rest of these images -->
<img data-src="unicorn.jpg" loading="lazy" alt=".." class="lazyload"/>
<img data-src="cats.jpg" loading="lazy" alt=".." class="lazyload"/>
<img data-src="dogs.jpg" loading="lazy" alt=".." class="lazyload"/>

<script> (async () => { if ('loading' in HTMLImageElement.prototype) { const images = document.querySelectorAll("img.lazyload"); images.forEach(img => img.src = img.dataset.src); } else { // Dynamically import the LazySizes library const lazySizesLib = await import('/lazysizes.min.js'); // Initiate LazySizes (reads data-src & class=lazyload) lazySizes.init(); // lazySizes works off a global. } })(); </script>
複製代碼

Andrea Verlicchi 有一篇關於 混合延遲加載 的好文章,值得一讀。

4、例子

A loading=lazy demo featuring exactly 100 kitten pics 能夠用,試試看。

(一)Chrome 開發細節

咱們強烈建議在 loading 屬性成爲穩定版本以前不要在生產環境中使用。

(二)如今試試

chrome://flags,打開 「Enable lazy frame loading」 和 「Enable lazy image loading」 標籤,而後重啓 Chrome。

(三)配置

Chrome 的延遲加載開發不只基於當前滾動的位置有多接近,還關係鏈接速度。對於不一樣的鏈接速度,延遲加載幀和圖像加載距離視口閾值是硬編碼的,可是能夠經過命令行覆蓋。下面是一個覆蓋圖像延遲加載視口閾值的例子:

canary --user-data-dir="$(mktemp -d)" --enable-features=LazyImageLoading --blink-settings=lazyImageLoadingDistanceThresholdPxUnknown=5000,lazyImageLoadingDistanceThresholdPxOffline=8000,lazyImageLoadingDistanceThresholdPxSlow2G=8000,lazyImageLoadingDistanceThresholdPx2G=6000,lazyImageLoadingDistanceThresholdPx3G=4000,lazyImageLoadingDistanceThresholdPx4G=3000 'https://mathiasbynens.be/demo/img-loading-lazy'
複製代碼

上述命令對應於默認配置。僅當滾動位置在圖片的 400 像素之內時,纔將全部的值變爲 400 纔開始延遲加載。下面咱們還將看到 1 像素的變化(本文前面的視頻使用):

canary --user-data-dir="$(mktemp -d)" --enable-features=LazyImageLoading --blink-settings=lazyImageLoadingDistanceThresholdPxUnknown=1,lazyImageLoadingDistanceThresholdPxOffline=1,lazyImageLoadingDistanceThresholdPxSlow2G=1,lazyImageLoadingDistanceThresholdPx2G=1,lazyImageLoadingDistanceThresholdPx3G=1,lazyImageLoadingDistanceThresholdPx4G=1 'https://mathiasbynens.be/demo/img-loading-lazy'
複製代碼

隨着配置在將來的幾周內穩定,咱們的配置有可能會發生變化.

4、開發者工具

Chrome 開發細節就是它在頁面加載的時候只抓取了 2KB 的圖片數據。若是服務器支持範圍請求,那麼前 2KB 可能會包含圖片尺寸。這使得咱們能夠生成或者展現一個具備一樣尺寸的佔位符。前 2KB 也有可能包含像字體那樣的整個圖像。

當用戶可以看見它們的時候,Chrome 抓取了剩下的圖片字節。Chrome DevTools 的一個警告就是延遲加載會致使:

  1. 在開發者工具網絡面板上會出現雙重提取。
  2. 資源計時在每一個圖片上都有兩次。

5、肯定服務器上的加載支持

一個完美的世界裏,你不須要依賴客戶端 JavaScript 功能檢測來決定是否須要加載一個回調庫——你應該在響應包含 JavaScript 延遲加載庫的 HTML 以前處理。客戶端提示能夠啓用此類檢查。

結束語

<img loading> 一個延伸,讓咱們知道你是怎麼想的。我對人們如何發現跨瀏覽器故事和其餘邊緣狀況特別感興趣。咱們但願在這個夏天的 Chrome 76 上發佈 loading 屬性。

相關連接

With thanks to Simon Pieters, Yoav Weiss and Mathias Bynens for their feedback. A large thanks to Ben Greenstein, Scott Little, Raj T and Houssein Djirdeh for their work on LazyLoad.

Last updated May 7th, 2019

原文連接:Native image lazy-loading for the web!

相關文章
相關標籤/搜索