众所周知,性能优化一般就两个东西, 不加载, 和缓存
当然不加载是不行的, 所以今天就来讲讲延迟加载
当前网页除了大规模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-background { background-image: url("hero-placeholder.jpg");
/* Placeholder image */}
.lazy-background.visible { background-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 , 欢迎关注