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!

相关文章
相关标签/搜索