✍️ 前端图片加载优化icar实践
一、背景
- 背景:xxcar官网的前端页面图片较多,导致页面加载缓慢
- 技术定位:中级
- 目标群体:开发人员
- 技术应用场景:[xxxicar官网]
- 整体思路:由于历史包袱比较重,为jquery加原生html实现,主要从图片资源,加载速度,cdn加速, 占位图,分块加载,硬件加速中考虑
二、操作步骤
2.1 图片资源文件迭代
换资源
由于前端使用的图片资源按分类主要有:图像分类(矢量图和位图)、压缩方式(有损和无损)、常见图像格式(JPEG、GIF、PNG、WebP、Base64)
-
官方不支持IE11了(推荐edge),将资源全量替换成webp,对图片进行瘦身
-
将占位符等需要缩放的图片用矢量图,替换成svg方式,方便进行三端展示不失帧
-
尽量可能使用字体图标替代一部分图片,防止首次加载页面进行多次网络请求
-
放弃做的工作
- 使用位图,小图片base64方式打包的目前架构不支持,重构代价太大
- 打包压缩雪碧图,目前架构不支持
2.2 滑动懒加载
1 对支持的浏览器直接使用load="lazy"
2 自己实现懒加载,在图片可视情况下,进行加载展示,否则不进行加载(可适用于背景图等方式加载的大图)- loadImage; 判断滚动位置和视窗关系,片进入视窗,则将其data-src属性赋值给src属性,从而触发图片加载
throttleLayLoad;使用Lodash的throttle函数对loadImage函数进行节流处理,使其在500毫秒内最多执行一次。- 为
scroll事件添加两个监听器;一个是经过节流处理的throttleLayLoad,另一个是原始的loadImage。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- 引入公共CSS文件 -->
<link rel="stylesheet" href="./common.css">
<!-- 引入Lodash库用于节流函数 -->
<script src="https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>
</head>
<body>
<!-- 使用data-src属性存储图片URL以实现懒加载 -->
<img data-src="https://img.36krcdn.com/20190808/v2_1565254363234_img_jpg">
<img data-src="https://img.36krcdn.com/20190905/v2_1567641293753_img_png">
<img data-src="https://img.36krcdn.com/20190905/v2_1567640518658_img_png">
<img data-src="https://img.36krcdn.com/20190905/v2_1567642423719_img_000">
<img data-src="https://img.36krcdn.com/20190905/v2_1567642425030_img_000">
<img data-src="https://img.36krcdn.com/20190905/v2_1567642425101_img_000">
<img data-src="https://img.36krcdn.com/20190905/v2_1567642425061_img_000">
<img data-src="https://img.36krcdn.com/20190904/v2_1567591358070_img_jpg">
<img data-src="https://img.36krcdn.com/20190905/v2_1567641974410_img_000">
<img data-src="https://img.36krcdn.com/20190905/v2_1567641974454_img_000">
<script>
// 获取所有图片元素
const imgs = document.getElementsByTagName('img');
const num = imgs.length; // 图片总数
let n = 0; // 已加载图片计数
// 懒加载图片的函数
function loadImage() {
let screenHeight = document.documentElement.clientHeight; // 视窗高度
let scrollTop = document.documentElement.scrollTop || document.body.scrollTop; // 滚动条位置
for (let i = 0; i < num; i++) {
// 检查图片是否进入视窗
if (imgs[i].offsetTop < screenHeight + scrollTop) {
// 设置图片src属性,触发加载
imgs[i].src = imgs[i].getAttribute('data-src');
n = i + 1;
// 如果所有图片已加载完毕,移除滚动事件监听器
if (n === num) {
window.removeEventListener('scroll', throttleLayLoad);
}
}
}
}
// 使用Lodash的节流函数,限制loadImage函数的执行频率
const throttleLayLoad = _.throttle(loadImage, 500);
// 添加滚动事件监听器,触发懒加载
window.addEventListener('scroll', throttleLayLoad);
window.addEventListener('resize', throttleLayLoad); // 添加窗口大小改变事件监听器
window.addEventListener('orientationchange', throttleLayLoad); // 添加屏幕方向改变事件监听器
// 页面加载完成后执行loadImage函数,确保首屏图片立即加载
document.addEventListener('DOMContentLoaded', loadImage);
</script>
</body>
</html>
2.3 节点 加速
将图片,视频,文件等资源放到cdn节点中,进行访问加速
2.4 decoding="async" 非首屏图片异步解码
解码图像和视频是计算密集型的操作,可能会占用大量的CPU资源,特别是对于高分辨率或者复杂编码格式的媒体文件,如果主线程被图像或视频的解码操作阻塞,用户在滚动页面或尝试交互时可能会感受到卡顿或延迟。
对非首屏图片或视频添加 decoding="async" 可以允许浏览器在后台处理图片、视频解码,而不阻塞主线程,继续处理和渲染页面的其余部分,这样可以有助于改善页面的加载性能,减少用户感知到的延迟,并提供更加平滑的用户体验。
<img src="image.jpg" decoding="async">
2.5 首屏图片 预加载
首页图片加载,确保初次加载时,用户可以立即看到主要内容
2.6 设计上规避或者弱化图片加载
- 隐式预加载:用户看第一张图的时候,悄悄加载后5张图
- 显式预加载:等待期间,出loading效果,明确告知用户需要价值图片
其他
-
其他资源访问也需要设置优化方式,防止其他资源阻塞了图片资源加载
-
content-visibility 另外一种懒加载( 兼容性 不好)
-
并发限制的话,目前浏览器性能提升较快,上限制提升较快,感觉没必要做
三、总结
总结本次技术应用中可积累的代码和经验
技术经验
有待提升
- 在现有的架构上,优化展示
- ......
- 对前后端的架构的深度,还需要加强
- ......