原生 HTML:懒加载
阻止下载图像或对象,直到它们在视口中可见 #2806
图片延迟加载 #3752
这篇文章和以往略有不同,我通常讨论的是浏览器中已经实现的功能,或是最近添加到规范中的新内容。今天我要探讨的是一些仍在等待合并到规范中的功能。
我希望这能让您更好地了解规范是如何随着时间推移而发展的,同时也能让您更有信心提出自己的改进建议。whatwg团队非常乐于接受新的想法。
W3错误报告
我们的故事始于 2012 年。BBC 网络团队的 Josh 将这个漏洞提交到了w3 网站上。
BBC最近更新了其BBC新闻移动网站。他们优化移动设备体验的方法之一是延迟加载图片,直到页面加载完毕后才加载。
我没有详细研究过具体实现方式,但他们使用了 DIV 元素作为占位符,用来表示图片将要放置的位置。例如:
<div class="delayed-image-load" data-src="http://static.bbci.co.uk/news/200/media/images/59388000/jpg/_59388680_59388679.jpg"></div>页面加载完成后,DIV 元素会变成 IMG 元素。
显然,这种做法语义化程度不高,而且如果禁用 JavaScript 则完全无效。但他们这样做有其合理理由,所以我认为有必要找到一种方法,将图片加载延迟到页面解析完成后再进行。这种方法也可以应用于其他嵌入式内容元素,例如 IFRAME 和 OBJECT。
我认为应该使用 DEFER 属性来实现这一点,它的作用方式与 SCRIPT 元素中的作用方式相同。
简单来说,他们希望能够使用一个<img>带有defer属性的标签,该属性会导致图像在网站加载完成之前不会渲染ready。
<img src="https://via.placeholder.com/150" defer />
这样一来,图像要等到第一次绘制完成后才会加载,从而使网站看起来加载速度更快。
GitHub 问题
几年后,这个话题就沉寂了,但在 2017 年,Josh 又在 GitHub 上提起了这件事。
阻止下载图像或对象,直到它们在视口中可见 #2806
参见 PR #3752
问题
许多网站都充斥着大量图片,但并非所有图片都会被访客浏览。尤其是在移动设备上,大多数访客很少向下滚动页面;他们主要关注的是页面顶部的内容。页面下方的图片大多不会被查看,但它们仍然会被下载。
这会减慢页面整体加载速度,不必要地增加部分访客的移动数据费用,并增加内存中保存的数据量。
示例解决方法
多年来,BBC 新闻团队一直使用以下方法来解决这个问题。页面顶部的正图以常规方式使用 `<img>`img元素包含在 HTML 文档中。然而,其他图片则通过脚本延迟加载。对于这些图片,它们最初以 `<img>`div元素的形式包含在 HTML 文档中,该元素充当占位符。`<img> div` 元素使用 CSS 设置样式,使其尺寸与加载的图片相同,并具有带有 BBC 徽标的灰色背景。
< div class =" js - delayed-image-load "
data-src =" https://ichef.bbci.co.uk/news/304/cpsprodpb/26B1/production/_96750990_totenhosen_alamy976y.jpg "
data-width =" 976 " data-height =" 549 "
data-alt =" Toten Hosen的坎皮诺" > </div>
img最终,当该元素在视口中可见时,脚本会将其替换为该元素。
使用脚本来实现这一点并不理想,因为:
- 如果访客禁用了脚本,或者脚本加载失败,则图片将永远不会显示。
- 我们无法预先知道访客的视口大小,因此只能随机决定延迟加载哪些图片。在新闻文章页面,视口较小的访客最初只能看到新闻图标和文章的首页图片,而视口较大的访客最初可以看到许多其他图片(例如侧边栏中的图片)。但为了兼顾移动设备,我们不得不优先考虑最小的兼容性。这导致视口较大的用户在页面加载时会遇到奇怪的问题:占位符图片会短暂出现。
- 我们必须等待脚本异步下载并执行完毕,然后才能将占位符替换为图像。
解决方案
需要提供一种原生方法,让作者无需使用脚本即可实现此功能。
一种解决方案是添加一个属性,用于声明哪些图像或对象在视口可见之前不应下载和解码。例如,<img lazyload>.*
或者,meta可以在 中放置一个元素,head将所有图像和对象全局设置为仅在它们在视口中可见时才下载。
*几年前,资源优先级规范中曾提出过一个同名属性,但它并没有阻止图像下载——它只是向浏览器提供了有关排序的提示,这在 HTTP/2 世界中可能不太有用。
乔什的想法稍有改动,但原理不变。他不再使用defer属性,lazyload而是使用一个仅用于加载视口中图像的属性。
<img src="https://via.placeholder.com/150" lazyload />
截至发稿时,该问题已获得 67 个赞、11 个欢呼和 29 个爱心表情。GitHub 的一大优势在于能够轻松地表达对问题的支持。
这次对话继续进行,并最终促成了一个 pull request!
GitHub 拉取请求
这个拉取请求来自一位名叫 Ben 的 Google 员工。大家正在添加代码片段并仔细阅读规范,以确保其合理性。截至 21 天前,所有评论都已得到解决,现在正在等待添加测试用例。
图片延迟加载 #3752
这是为支持 iframe 和 img 元素中的 lazyload 属性而制定的规范变更草案。
问题:#2806 测试:https://chromium-review.googlesource.com/c/chromium/src/+/1417117 ( wpt export )
/embedded-content.html(差异)/images.html(差异)/index.html(差异)/indices.html(差异)/media.html(差异)/rendering.html(差异)/urls-and-fetching.html(差异)
潜在规格
我们来看看描述,这次时间太早,还不能去 Mozilla 网站查看。
该属性为用户代理提供提示,以帮助其根据该属性的当前状态决定是立即加载元素还是延迟加载直到元素可见。
on
表示强烈倾向于延迟获取元素的资源,直到该元素可见为止。关闭
表示无论元素是否可见,都必须立即获取该元素的资源。auto
表示用户代理可以决定获取策略(默认值)。属性的
missing value default和invalid value default都是auto状态。
以下是一些实际例子
<!--
this image will not be fetched until it
is in the viewport, meaning the page loads
faster and uses less data.
-->
<img src="https://via.placeholder.com/150" lazyload="on" />
<!--
this image will be fetched as soon as the
page opens, this is how website work currently
-->
<img src="https://via.placeholder.com/150" lazyload="off" />
<!--
this image will probably work the same as off
but there is space for interpretation
-->
<img src="https://via.placeholder.com/150" lazyload="auto" />
<!--
If the lazyload value is invalid or missing
the attribute will default auto
-->
<img src="https://via.placeholder.com/150" lazyload="bar" />
<img src="https://via.placeholder.com/150" />
总结
我认为,任何可以交给浏览器处理的数据都能让网络体验更好。让所有图片都懒加载,无需开发团队付出任何努力,这对我来说很有意义。你们有什么想法吗?请在下方留言。
如果您认为规范中缺少某些内容,请前往相应的issue页面告知他们。规范更新是一个非常精细的过程,在浏览器实现之前,他们获得的帮助越多越好。
感谢阅读,我知道这篇文章和我的其他文章有点不一样,但我仍然觉得它很有趣。
❤🦄🦄❤🦄❤🦄🦄❤
文章来源:https://dev.to/link2twenty/native-html-lazyloading-3ai4