基于古老项目的前端图片加载优化实践(jquery,html)

101 阅读4分钟

✍️ 前端图片加载优化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 另外一种懒加载( 兼容性 不好)

  • 并发限制的话,目前浏览器性能提升较快,上限制提升较快,感觉没必要做

三、总结

总结本次技术应用中可积累的代码和经验

技术经验

有待提升

  • 在现有的架构上,优化展示
  • ......
  • 对前后端的架构的深度,还需要加强
  • ......