网页应用性能下降的罪魁祸首,以及懒加载的必要性

在现代网页应用中,图片是影响用户体验(UX)和网页性能的关键因素之一。随着高分辨率图片使用的增加,页面内图片内容的比例不断上升,网页加载速度下降已成为不可避免的问题。一次性加载所有图片的方式会导致以下致命的性能瓶颈。

  • 初始加载时间增加 (FCP, LCP 延迟):由于下载了视口外的图片,用户真正看到内容的时间点(首次内容绘制)和最大内容元素加载的时间点(最大内容绘制)大幅延迟。这对核心网页指标也有不利影响。

  • 不必要的带宽消耗:即使用户不会滚动查看的图片,也会浪费网络资源,这在移动环境中增加了数据费用的负担,并在桌面环境中也会由于不必要的网络请求干扰到其他重要资源的加载。

  • 服务器负荷增加:所有图片请求同时发生,会给服务器带来过大的负荷,这可能导致服务的稳定性下降。

解决这些问题的最有效策略之一就是图片懒加载。懒加载技术是在网页初始加载时不加载所有图片,而是在用户的视口内进入时或达到某个阈值时异步加载对应图片的技术

图片懒加载的工作原理及应用方法

懒加载的主要应用方式可以分为两种,需理解各自的优缺点,并根据项目需求进行选择。

1. 浏览器原生懒加载 (loading="lazy")

这是最简单且强大的方法,只需在HTML <img>标签中添加 loading="lazy" 属性即可实现。这在大多数最新浏览器中得到了支持,并由浏览器自身优化处理懒加载。

<img src="placeholder.jpg"
     data-src="actual-image.jpg"
     alt="图片描述"
     loading="lazy"
     width="500"
     height="300">
  • 优点:

    • 实现简单:只需在HTML中添加属性,无需额外的JavaScript代码即可应用。

    • 性能优化:由于是在浏览器引擎级别实现,因此可以比基于JavaScript的解决方案更高效、更快速地运行。

    • 开发者负担减少:无需复杂的Intersection Observer API或事件监听管理,浏览器会自动处理。

  • 缺点:

    • 浏览器支持:可能无法在所有遗留浏览器中完美支持。(但大多数现代浏览器都支持)

    • 缺乏细致控制:开发者难以细致控制加载阈值或加载策略。

建议:如果没有特殊控制需求,建议优先应用原生懒加载

2. 基于JavaScript的懒加载 (使用Intersection Observer API)

当需要更细致的控制,或者在不支持 loading="lazy" 属性的浏览器中需要回退方案时,可以实现基于JavaScript的懒加载。过去主要使用滚动事件监听器,但由于性能问题,现在标准是使用Intersection Observer API

基本实现逻辑:

  1. 初始时在图片的 src 属性中指定占位符图片,或在 data-src 属性中保存实际图片URL。

  2. 创建Intersection Observer实例,观察图片元素。

  3. 当图片元素进入视口或达到定义的阈值时,执行Observer回调函数。

  4. 在回调函数中,将存储在 data-src 中的实际图片URL转移到 src 属性,从而加载图片。

  5. 图片加载完成后,停止对该图片元素的观察。

// HTML (示例)
// <img class="lazyload" data-src="actual-image.jpg" alt="描述">

// JavaScript
document.addEventListener("DOMContentLoaded", function() {
    const lazyImages = [].slice.call(document.querySelectorAll("img.lazyload"));

    if ("IntersectionObserver" in window) {
        let lazyImageObserver = new IntersectionObserver(function(entries, observer) {
            entries.forEach(function(entry) {
                if (entry.isIntersecting) {
                    let lazyImage = entry.target;
                    lazyImage.src = lazyImage.dataset.src;
                    // lazyImage.srcset = lazyImage.dataset.srcset; // 如果需要srcset
                    lazyImage.classList.remove("lazyload");
                    lazyImageObserver.unobserve(lazyImage);
                }
            });
        }, {
            // Root Margin: 从视口边缘预加载图片的区域(px或%)
            // 示例:"0px 0px 200px 0px" 表示向下预加载200px
            rootMargin: "0px 0px 200px 0px"
        });

        lazyImages.forEach(function(lazyImage) {
            lazyImageObserver.observe(lazyImage);
        });
    } else {
        // IntersectionObserver不支持的浏览器回退
        // (例如:使用滚动事件监听器,或立即加载所有图片)
        // 该部分在性能上不推荐,因此应根据主要目标浏览器进行判断
        lazyImages.forEach(function(lazyImage) {
            lazyImage.src = lazyImage.dataset.src;
        });
    }
});
  • 流行的JavaScript懒加载库:

    • lazysizes: 非常轻量,并且对SEO友好,支持包含 srcsetpicture 元素的多种图片格式。也可以用作原生懒加载的回退。

    • lozad.js: 拥有小的捆绑大小和高性能。

懒加载应用时考虑事项及优化提示

懒加载是一种强大的性能优化技术,但无节制地应用于所有图片,反而可能会损害用户体验。

  1. ‘Above the Fold’ 图片管理: 对于初始屏幕(视口)中立即可见的图片(Above the Fold),不应应用懒加载。这些图片会直接影响页面的最大内容绘制(LCP),因此需要明确设置 loading="eager",或将其排除在懒加载之外,确保能够立即加载。
<img src="logo.png" alt="公司logo" width="100" height="50" loading="eager">

LCP breakdown analysis

  1. 明确 widthheight 属性: 在HTML中明确图片的 widthheight 属性,以防止布局偏移(Cumulative Layout Shift, CLS)。使浏览器在加载图片之前预留图片的空间,从而避免在加载过程中布局的晃动。这对于提升核心网页指标的分数至关重要。

  2. 使用占位符图片: 为了在懒加载图片加载之前给用户保留视觉空间,建议使用模糊的低分辨率图片或单色背景的占位符。这样可以向用户表明页面正在加载。

  3. 利用 srcset<picture> 标签: 将响应式图片(srcset)和艺术指导(picture标签)与懒加载一起使用,以提供适合不同屏幕大小和分辨率的优化图片,并进一步减少不必要的图片下载。

<picture>
    <source srcset="image-large.webp" type="image/webp" media="(min-width: 1200px)" loading="lazy">
    <source srcset="image-medium.webp" type="image/webp" media="(min-width: 768px)" loading="lazy">
    <img src="placeholder.jpg" data-src="image-small.jpg" alt="描述" loading="lazy">
</picture>

Lighthouse performance score

结论:兼顾性能和用户体验的懒加载

图片懒加载不仅仅是延迟图片加载,更是显著改善网页的初始加载性能,优化带宽使用,减少服务器负担的必备网页优化技术。随着核心网页指标等网页性能指标的重要性日益增强,懒加载的战略性应用成为开发者必须考虑的事项。

优先考虑原生懒加载,但在需要细致控制或需支持特定浏览器环境的情况下,考虑使用基于Intersection Observer API的JavaScript实现或利用相应库。此外,还应在‘Above the Fold’图片管理、明确 width/height、使用占位符等优化提示中结合应用,以提供快速舒适的网页体验给用户。