@wy
2019-04-16T23:20:51.000000Z
字数 4998
阅读 889
翻译
在这篇文章中,我们将看到新的 loading 属性,将实现原生的< img> 和 < iframe>延迟加载到 web 网页上。对于好奇的人来说,先睹为快一段实际的预览代码:
<img src="celebration.jpg" loading="lazy" alt="..." />
<iframe src="video-player.html" loading="lazy"></iframe>
我们希望在 Chrome 75中提供对 loading 的 支持,并正在深入研究我们即将发布的功能。 在此之前,让我们深入了解 loading 的工作原理。
网页通常包含大量图片,这些图片会影响数据使用,导致页面膨胀以及页面加载的速度。许多这些图片都在屏幕外,需要用户滚动才能看到它们。
从历史上看,为了限制屏幕外图片对页面加载时间的影响,开发人员需要使用JavaScript库(如 LazySizes)来延迟获取这些图片,直到用户滚动到它们为止。
一个页面加载了211张图片。没有延迟加载的版本要获取10MB的图片数据。 延迟加载版本(使用LazySizes)预先加载250KB - 当用户滚动体验时,再获取其他图片。 见 WPT。
如果浏览器可以避免为你加载这些屏幕之外的图片呢?这将有助于更快地加载视图端口(译者注:可视区域)中的内容,减少总体网络数据使用,并在低端设备上减少内存使用。好吧,我很高兴与大家分享,很快就可以在图片和 iframe 上使用新加载属性实现了。
loading 属性允许浏览器延迟加载屏幕之外的图片和 iframe,直到用户滚动到它们附近。loading 支持三个值:
如果不指定属性将产生与设置 loading=auto 相同的影响。
正在努力让 < img> and < iframe> 的 loading 属性作为 HTML 标准( HTML standard)的一部分。
loading 属性适用于 < img>(包括具有srcset和< picture>内部)以及 < iframe> 上
<!-- 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>
The exact heuristics for "when the user scrolls near" is left up to the browser.一般来说,我们希望浏览器能够在进入视口之前开始获取延迟的图片和iframe的一些内容。当用户滚动到它们时,这将提高图片或者iframe完成加载。
注意:我建议我们将其命名为 loading 属性,因为它的命名与 decoding 属性更接近。之前的提议,诸如 lazyload 属性没有使用,---------并不像我们需要的那样支持多个值(lazy, eager 和 auto)。
我们牢记能够获取和应用 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.jpg loading=lazy/> 时,仅使用功能检测和延迟加载的库是不够的。在标签中需要使用类似于 < img data-src=unicorn.jpg/>(而不是src、srcset或< source>)的内容,以避免在不支持新属性的浏览器中触发立马加载。如果支持 loading,可以使用 JavaScript 将这些属性更改为正确的属性,否则加载库来更改。
下面是一个这样的例子。
视口内/一屏显示(above-the-fold)的图片是常规的 < img> 标签。 使用 data-src 会破坏预加载扫描程序,因此我们使用它是希望避免在视口中所有的内容。
我们在图片上使用 data-src 以避免在不受支持的浏览器中出现立马加载。 如果支持 loading,我们将 data-src 交换为 src。
<!-- 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>
我们强烈建议您在生产中使用它之前等待 loading 属性处于稳定版本。早期测试人员可能会发现以下注释(暂定)很有帮助。
在地址栏输入 chrome://flags 并打开 "Enable lazy frame loading" 和 "Enable lazy image loading" 的标志,然后重启 Chrome。
Chrome 的延迟加载实现不仅基于当前滚动位置的远近,还基于连接速度。对于不同连接速度,延迟帧和图片加载距离视口的阈值是硬编码( hardcoded),但是可以通过命令行覆盖。下面是覆盖图片的延迟加载设置的示例:
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'
我们的默认配置很可能会随着实现在未来几周的稳定而改变。
在 Chrome 中加载的实现细节是它在页面加载时获取前2KB的图像。 如果在服务器支持范围请求,则前2KB可能包含图像尺寸。 这使我们能够生成/显示具有相同尺寸的占位符。 前2KB也可能包括像图标这样的整个图片。
当用户即将看到它时,Chrome会获取剩余的图片字节。 Chrome DevTools 的一个警告是,这可能导致(1)在DevTools网络面板中“出现”双重提取和(2)资源计时对每个图像有2个请求。
在理想的情况下,您不需要依赖客户端上的 JavaScript 特性检测来决定是否需要回退到引入库来完成加载—-—
给 < img loading> 提一些建议让我们知道您的想法。我特别感兴趣的是人们如何找到跨浏览器的故事,以及我们是否遗漏了任何边缘情况。