最简单的性能优化的利器 延迟加载

104 阅读2分钟

众所周知,性能优化一般就两个东西, 不加载, 和缓存

当然不加载是不行的, 所以今天就来讲讲延迟加载

当前网页除了大规模js加载,还有一些我们可以进行优化的地方

对于字体文件加载, 可以看我的文章- 字体模块设计

图片加载

图片性能优化包含很多内容, 包括压缩, 格式, 用视频替换GIF, 根据尺寸提供图片, 使用webp, 使用cdn. 这些不是我们今天的内容,今天来看看图片延迟加载 最新的浏览器默认实现浏览器级别的延迟加载, 可以使用loading属性来开启

<img loading="lazy" />

我们还可以通过 IntersectionObserver 对象,来开启对img的延迟加载更精细的控制, 例如在视口中出现1s以上才开始显示图片

// 获取所有需要延迟加载的图片元素
const lazyImages = document.querySelectorAll(".lazy-loaded-image");

// 设置 IntersectionObserver 的选项
const options = {
  root: null,
  rootMargin: "0px",
  threshold: 0.5
};

// 创建 IntersectionObserver 对象
const lazyImageObserver = new IntersectionObserver((entries, observer) => {
  entries.forEach((entry) => {
    if (entry.isIntersecting && entry.intersectionRatio >= 0.5) {
      // 如果图片在视口中出现1s以上,开始加载图片
      setTimeout(() => {
        const lazyImage = entry.target;
        lazyImage.src = lazyImage.dataset.src;
        lazyImage.classList.remove("lazy");
        lazyImageObserver.unobserve(lazyImage);
      }, 1000);
    }
  });
}, options);

// 观察所有需要延迟加载的图片元素
lazyImages.forEach((lazyImage) => {
  lazyImageObserver.observe(lazyImage);
});

css文件中的图片

css文件中的图片不可以用上面的加载方式, 但是我们同样可以使用视口监视的方式,来动态添加类名已达到延迟加载图片的目的

.lazy-backgroundbackground-image: url("hero-placeholder.jpg");
/* Placeholder image */}
.lazy-background.visiblebackground-image: url("hero.jpg"); 
/* The final image */}

我们通过修改上面的代码将setTimeout 中的内容替换为(其他代码相对应的改动)

   lazyBackGround.classList.add("visible");

来达到动态改变css加载的图片方式实现延迟加载

视频的延迟加载

video没有 lazy 属性, 但是有个preload可以使用

<video controls preload="none" poster="one-does-not-simply-placeholder.jpg">  <source src="one-does-not-simply.webm" type="video/webm">  <source src="one-does-not-simply.mp4" type="video/mp4"></video>

这里有个poster 属性, 这个属性非常有用,可以将图片当作占位图来使用

前文提到过,我们可以使用视频来替换GIF显示,这是因为相同内容, 视频相对于GIF有明显的体积优势

这种场景下,我们的video标签是这样的 这是一个延迟加载的, 自动播放, 一直循环的视频

<video class="lazy" autoplay muted loop playsinline width="610" height="254" poster="one-does-not-simply.jpg">  <source data-src="one-does-not-simply.webm" type="video/webm">  <source data-src="one-does-not-simply.mp4" type="video/mp4"></video>

我们依然可以使用 IntersectionObserver 来动态的替换source元素的src ,来精细的控制延迟加载

if (video.isIntersecting) {
  for (var source in video.target.children) {
    var videoSource = video.target.children[source];
    if (
      typeof videoSource.tagName === 'string' &&
      videoSource.tagName === 'SOURCE'
    ) {
      videoSource.src = videoSource.dataset.src;
    }
  }
  video.target.load();
  video.target.classList.remove('lazy');
  lazyVideoObserver.unobserve(video.target);
}

iframe 的延迟加载

iframe 同样支持loading=lazy, 最简单的方法就是直接添加到标签上, 这对于页面中嵌入大量视频的场景非常有效

about me

我是meanc , 欢迎关注