完整指南:如何通过延迟加载图片来提升网站性能
2019-2020年的疫情让我们都变得懒惰起来。由于别无选择,只能待在家里,35.82%的人在那段时间体重增加了,这都要“归功于”我们的懒惰。幸运的是,这段时期也给了我们一个绝佳的机会,去理解Web开发中一个与之有些类似的概念。那么,你如何定义“懒惰”这个词呢?谷歌的解释是“不愿工作”,但我可以把它重新表述为“不到万不得已不愿工作”。除非懒人真的非常需要离开那张破沙发,否则他们会一直赖在沙发上不走。
类似地,在 CSS 中,我们称那些只有在绝对必要的情况下才会从服务器加载到客户端(就像从沙发上到 X 点一样)的图片为“懒加载图片”。懒加载图片将是这篇博客的核心。文章将围绕如何鼓励开发者在现实生活中避免图片加载延迟展开。文章的主要内容将阐述懒加载图片的概念、懒加载方法以及开发者如何将图片转换为懒加载图片。
什么是图片懒加载?
在图像处理或计算机科学领域,延迟加载的概念是指在绝对必要时才请求获取特定元素。例如,在 Scala 中,我们使用延迟加载变量来避免在必要时才进行初始化和计算。这可以加快程序运行速度并减少内存消耗。
在 CSS 中,也采用了类似的概念,即仅在必要时加载图片。图片体积庞大,会显著增加页面加载量。谷歌的分析显示,图片平均占网页字节数的 60% 以上。如果您拥有网站,也可以查看页面速度分析数据,了解图片如何导致网页加载过快。
除了懒加载之外,开发者还可以尝试很多方法来优化网页性能。这些方法包括了解图片的响应式设计、减小图片尺寸以及使用正确的图片格式。但是,无论我们做什么,图片仍然是网页的重要组成部分,如今没有合适的图片,网页就称不上完整。因此,我们需要一些方法,既能提升网页性能,又不至于舍弃任何图片。
如今,图片对网页的贡献非常大,因为它们确实很重要!
一项研究表明,65% 的人通过视觉图像学习,而 Brandwatch 的另一项研究则强调,每天有 32 亿次图像共享。
我们无法跳过网页上的图片,这就引出了一种新的技术,既能加载图片又能节省带宽。这就是图片懒加载的用武之地。图片懒加载的理念是,并非所有访问网页的用户都会完整阅读到最后。有些人只是随意浏览网页,结果发现页面与他们无关。有些人则会在不需要浏览到某个页面时直接关闭它。
对所有用户同时加载页面会浪费带宽,还会流失潜在用户,因为我们知道大多数用户等待加载的时间不会超过2秒。所以,为什么不跳过图片加载,等到用户浏览到图片所在的页面时再加载呢?这样,即使向用户发出较大的请求,也是值得的!对于那些在图片加载完成前离开页面的用户,网页速度会更快,服务器请求也会减少。这可谓双赢。
从下一节开始,我们将讨论三种“如何延迟加载图像?”的方法——困难的方法、一般的方法和简单的方法!
使用 JavaScript 实现图片懒加载——笨办法
首先要介绍的是长期以来用于实现图片懒加载的传统方法。用 JavaScript 实现图片懒加载比本文讨论的其他方法要复杂一些,但我相信它能帮助你提升 JavaScript 技能,并带来诸多好处。
要在网页上加载图像,我们使用带有“src”属性的“img”标签,该属性定义图像的URL。
<img src = “URL” />
要对“img”标签应用延迟加载,我们需要先移除“src”标签。原因是浏览器在遇到“src”标签时会快速加载所有URL。因此,当我们等待JavaScript触发事件时,一旦文档对象模型(DOM)加载完毕,浏览器就已经加载了图片。
为了防止图像自动加载,我们使用 data-src 属性而不是 src 属性。
<img data-src = “URL” />
在本演示中,我们将使用“滚动”事件来触发 JavaScript 函数,但由于这是您的网站,您可以根据自己的喜好选择任何事件来让浏览器知道加载图像的时间。
为了让浏览器知道我们要在事件发生后调用一个函数,我们需要按如下方式添加事件监听器:
document.addEventListener(“scroll”, function_name);
这里,我们需要将 `function_name` 替换为实际的函数名。假设我们的函数名为“Wake_Up_Image”,用于检查图像是否在视口中。如果在,则唤醒图像,即加载它。
document.addEventListener(“scroll”, Wake_Up_Image);
现在我们需要按如下方式实现我们的函数:
function Wake_Up_Image() {
if(lazyloadTimeout) {
clearTimeout(lazyloadTimeout);
}
lazyloadTimeout = setTimeout(function() {
var scrollTop = window.pageYOffset;
lazyImages.forEach(function(img) {
if(img.offsetTop < (window.innerHeight + scrollTop)) {
img.src = img.dataset.src;
}
});
}
上述函数遍历图像并计算图像相对于窗口的偏移量,从而确定视口。如果图像位于视口内,则将之前使用的data-src标签转换为srcsrc标签img.src = img.dataset.src。浏览器检测到 src 标签后,会在网页上加载图像。
超时功能用于优化和提升性能。这段代码在浏览器中可以正常运行,但需要进行一些性能优化。
首先,我们需要将需要延迟加载的图像捕获到 lazyImages 中。为此,我们可以在图像标签中实现“ lazy ”类。
<img class = “lazy” data-src = “URL” /><pre>
Now we can capture these images using querySelector as follows:
<strong>var lazyImages = document.querySelectorAll("img.lazy");</strong>
As a next step, we should remove the eventListener as soon as the timeout becomes 0. This can be achieved through the removeEventListener:
<strong>document.removeEventListener("scroll", Wake_Up_Image);</strong>
Combining all of the above changes and optimizations, the overall code becomes:
<pre>
var lazyImages = document.querySelectorAll("img.lazy");
var lazyloadTimeout;
function Wake_Up_Image() {
if(lazyloadTimeout) {
clearTimeout(lazyloadTimeout);
}
lazyloadTimeout = setTimeout(function() {
var scrollTop = window.pageYOffset;
lazyImages.forEach(function(img) {
if(img.offsetTop < (window.innerHeight + scrollTop)) {
img.src = img.dataset.src;
img.classList.remove('lazy');
}
});
if(lazyloadImages.length == 0) {
document.removeEventListener("scroll", lazyload);
}
}, 15);
}
document.addEventListener("scroll", lazyload);
});
如果需要,您可以添加其他事件监听器,例如屏幕方向改变或窗口大小调整。
上述代码会产生以下输出:
好了!通过这种方式,我们已经完成了实现图片懒加载的复杂方法。作为一名 Web 开发人员,我在开发网页时可能不会使用 JavaScript 来实现图片懒加载。如果最终目的只是根据图片在视口中的可见性来加载它们,那么 JavaScript 比其他方法更繁琐、更复杂。它更容易出错,代码也更难读懂。不过,如果你打算根据事件监听器来控制图片,那么没有什么比 JavaScript 更合适的了。
在上面的演示中,您可能会感觉到图片加载略有延迟,此时画布会显示为灰色。作为开发者,您可以给画布添加一些醒目的颜色,以避免用户注意到这种延迟。这只是一个细微的 UI 调整,不会影响图片懒加载的性能。
使用 Intersection Observer API 实现图片懒加载——平庸之道
鉴于对基于视口的功能的高需求,JavaScript 引入了一个名为Intersection Observer 的新 API。Intersection Observer API 用于观察目标元素与其祖先元素或顶层文档视口的交集。与传统方法相比,Intersection Observer API 省略了 JavaScript 中常见的条件语句、循环语句和事件处理程序,从而避免了代码的复杂性。
我们将对上述代码进行修改,使其符合交叉路口观察器 API 的要求,具体如下:
document.addEventListener("DOMContentLoaded", function() {
var lazyImages;
if ("IntersectionObserver" in window) {
lazyImages = document.querySelectorAll(".lazy");
var imageObserver = new IntersectionObserver(function(entries, observer) {
entries.forEach(function(entry) {
if (entry.isIntersecting) {
var image = entry.target;
image.src = image.dataset.src;
image.classList.remove("lazy");
imageObserver.unobserve(image);
}
});
});
lazyImages.forEach(function(image) {
imageObserver.observe(image);
});
} else {
var lazyloadTimeout;
lazyImages = document.querySelectorAll(".lazy");
function lazyload () {
if(lazyloadTimeout) {
clearTimeout(lazyloadTimeout);
}
lazyloadTimeout = setTimeout(function() {
var scrollTop = window.pageYOffset;
lazyImages.forEach(function(img) {
if(img.offsetTop < (window.innerHeight + scrollTop)) {
img.src = img.dataset.src;
img.classList.remove('lazy');
}
});
if(lazyloadImages.length == 0) {
document.removeEventListener("scroll", lazyload);
}
}, 15);
}
document.addEventListener("scroll", lazyload);
}
})
“unobserve”方法指示交叉点观察器停止观察目标元素,而“observe”方法则相反。请注意,我们在使用API时移除了事件处理程序和偏移量计算。
上述代码生成以下输出:
如上文在LambdaTest上进行的交互视频所示,Intersection Observer API 速度更快,滚动事件的处理也更加出色。使用 JavaScript 编写代码时产生的延迟在 API 中也完全消失了。
浏览器对交叉路口观察器 API 的支持
浏览器对交叉路口观察器 API 的支持也非常好,让我们能够自由地使用它,而不用担心崩溃:
Intersection Observer API 是网页上图片延迟加载的更佳选择。浏览器也提供了一种更直接的图片延迟加载方法,称为“loading”属性。
使用 Loading 属性实现图片懒加载——简单方法
网页内容随着时间推移而不断增长。开发者们现在意识到,图片对用户及其对网站的感知有着显著的影响。因此,如今几乎没有网页完全没有图片。有些网页甚至充斥着图片,数量超过十张,有时甚至达到十五张。虽然这对所有人来说都是好事,但谷歌Chrome的开发者们也开始认真对待网页的懒加载功能。
随着网页体积的显著增长,开发者开始在网站上使用懒加载技术,以避免网页加载速度慢到令人尴尬的情况。因此,谷歌 Chrome 的开发者们想到将这项功能集成到浏览器原生库中,这样开发者就可以省去编写复杂 JavaScript 代码的步骤,直接利用 src 属性来实现懒加载。这个属性被称为“加载中”属性。
“loading”属性由三个值组成:
- auto:此值取决于浏览器的内置功能。例如,Google Chrome 会自动加载位于视口深处的图片以节省带宽。如果其他浏览器不具备此功能,则图片会随页面一起立即加载。
- lazy: “lazy” 值告诉浏览器此图像需要在浏览器中延迟加载。
- eager: “eager” 值用于指示浏览器在内容加载完毕后立即加载图像。“eager” 值与“lazy” 值相反。
由于我们需要延迟加载图片,因此这里将使用“ lazy ”值。这是基于 Chromium 的更新,因此所有基于 Chromium 的浏览器都将可以使用此功能。
无需使用 JavaScript,只需在图像标签中添加少量代码即可,如下所示:
<img src = “URL” loading = “lazy”>
上述代码无需任何额外代码即可输出与 Intersection Observer API 相同的结果。那么,为什么不直接使用原生懒加载功能呢?
浏览器对加载属性的支持
浏览器对 loading 属性的支持情况如下:
Chrome 浏览器和其他基于 Chromium 内核的浏览器都完全支持该属性。相比之下,Mozilla 的 Firefox 目前仅提供部分支持。“loading”属性更容易访问,但正如我上面提到的,如果您想操作事件并更好地控制元素,JavaScript 才是最佳选择。
图片懒加载 JavaScript 库
上述方法需要您编写复杂的代码来处理每个条件和循环,而且没有任何支持。然而,就像其他任何操作一样,JavaScript 也提供了解决方案,它拥有许多库,不仅可以支持图像的延迟加载,还可以支持其他元素的延迟加载。以下库可以帮助您在 JavaScript 中实现元素的延迟加载:
除此之外,对于 WordPress 用户来说,可以使用A3 Lazy Load 插件来非常高效地实现懒加载。
你最喜欢哪个选项?
图片延迟加载是提升网站性能的绝佳方案。如果您的网页包含少量图片,且这些图片分散在网页的不同区域,延迟加载可以节省网络请求次数,从而缩短网站加载时间。不仅如此,延迟加载还能显著提升性能并降低总体成本。对于将所有图片托管在 AWS 云上的用户而言,减少服务器请求次数可以有效降低每月账单费用。
这并不意味着我们要对网页上的所有内容都进行延迟加载。虽然延迟加载所有内容听起来能显著提升性能,但实际上并非必要。如今的服务器速度并不慢,网络速度也更快。如果开发者将原本可以通过单个请求获取的内容拆分成多个部分,延迟加载反而会增加服务器调用次数。因此,建议使用延迟加载,但并非所有地方都需要。
本文介绍的方法旨在实现网页图片的懒加载。目前有三种方法可供选择,它们各有优缺点。JavaScript 可能比较复杂,但能提供更大的控制权。加载属性只需几秒钟即可完成,但并非所有浏览器都能完美渲染。我们目前有三种选择,作为开发和测试社区的一员,我们很想了解大家对这些方法的看法,以及你们更倾向于哪一种。请在评论区分享你使用的方法及其原因,帮助社区从其他开发者那里获得更多个人见解。
测试愉快!
文章来源:https://dev.to/harishrajora12/complete-guide-to-lazy-load-images-for-better-website-performance-6ck



