浏览器系列 — 优化网页图片加载

对优化网页图片加载有如下6种方案:

  1. 图片压缩
  2. 先加载压缩图片,再加载高清大图,加载完毕后代替掉
  3. 使用base64、css、canvas代替简单图片
  4. 图片预加载
  5. 图片懒加载
  6. 使用 CDN 加速

1. 图片压缩

从视觉上没有影响的前提下对图片的大小进行压缩,可以从根本上很好地解决网页加载图片慢的问题

图片压缩方式分为两个方面:

  • 一方面是减少一张图片总的像素个数

如果屏幕像素是 450 * 750 ,那1080 * 1920 的高清大图是没有必要的了,利用外部软件进行压缩即可

  • 另一方面是减少单位像素所需的字节数

举个例子:一张图片的每个像素点通过 RGBA 颜色值进行存储,R\G\B\A 每个色道都有 0~255 个取值,也就是 2^8 = 256。正好是 8 位 1byte。而每个像素点有四个色道,每个像素点需要 4bytes

RGBA 颜色值可以表示 256^4 种颜色,这是一个很大的数字,往往我们不需要这么多颜色值。因此我们是否可以减少色板中的颜色种类呢?这样表示单位像素的字节数就减少了。

而「无损」压缩是通过一些算法,存储像素数据不变的前提下,尽量减少图片存储体积。比如一张图片中的某一个像素点和其周围的像素点很接近,比如一张蓝天的图片,因此我们可以存储两个像素点颜色值差值,这样表示单位像素的字节数就减少了

2. 先加载压缩图片,再加载高清大图,加载完毕后代替掉

压缩图是 photo_min.jpg ,对应的高清大图是 photo.jpg

<body>
    <div class="box">
        <img src="../images/photos/culture/photo.min.jpg">
    </div>
</body>
<script>
    $(function() {
        //一段正则,匹配所有_min.的图片src属性
        var test = /_min\./
            //遍历所有的图片节点
        $("img").each(function(index, obj) {
            if (test.test($(this).attr("src"))) {
                var reSrc = $(this).attr("src").replace(test, "."); // 完成替代
                $(this).attr("src", reSrc)
            }
        })
    })
</script>
复制代码

3. 使用base64、css、canvas代替简单图片

对于一些较为简单的图片可以采用base64、css、canvas等代替

使用base64代替图片

  • 原理:将图片转换为base64编码字符串inline到页面或css中

background-image: url("data:image/png;base64,iVBORw0KGgo=...");
<img src="data:image/png;base64,iVBORw0KGgo=..." />

  • 场景:适用于图片大小小于2KB,页面上引用图片总数不多的情况
  • 优势:1. 减少http的请求次数; 2. 并可以放到后台数据库中,只传输字符串,更快
  • 图片太大对应的字符串过长,也不利于传输

使用CSS代替图片

  • 原理:使用before或者after伪元素来丰富图案的复杂度。
  • 场景:适用于移动端或较高级的浏览器,用于绘制简单图案
  • 优势:具有实现简单,图片体积小的特点,可以实现简单的动态效果
  • 劣势:也受限于css的兼容性特点,绘制复杂图案困难

canvas代替图片

  • 原理:html5的canvas元素
  • 场景:绘制高性能的图片或动画
  • 优势:整个就是画2D图形时,页面渲染性能比较高,页面渲染性能受图形复杂度影响小,性能只受图形的分辨率的影响,画出来的图形可以直接保存为 .png 或者 .jpg的图形,适合于画光栅图像或者不规则图形
  • 劣势:没有dom操作,必须依赖定时器,文字渲染性能差,不能添加图片描述,兼容性限制

具体关于Canvas的内容可以看 HTML系列 — Canvas

4. 图片预加载

资源预加载是一个性能优化技术,我们可以使用该技术来预先告知浏览器某些资源可能在将来会被使用到

DNS 预解析 rel=”dns-prefetch”

例如,我们将来可能加载名为 image.png 这种图片,那么可以在文档顶部的 <head>标签中加入以下内容:
<link rel="dns-prefetch" href="image.png">
通过简单的一行代码就可以告知那些兼容的浏览器进行 DNS 预解析,这意味着当浏览器真正请求该域中的某个资源时,DNS 的解析就已经完成了

预获取 rel=”prefetch”

与 DNS 预解析不同,预获取真正请求并下载了资源,并储存在缓存

在文档顶部的 <head>标签中加入以下内容:<link rel="prefetch" href="image.png">

预渲染 rel=”prerender”

对一个用户将来一定会打开的 tab 页:将【下载所有资源、创建 DOM 结构、完成页面布局、应用 CSS 样式和执行 JavaScript 脚本】等。当用户真正访问该链接时,隐藏的页面就切换为可见,使页面看起来就是瞬间加载完成一样

前提是:用户在将来一定会打开该tab页,否则会造成不必要的资源浪费

5. 图片懒加载

在用户即将看到图片时进行加载,如果位处于视窗区域内则暂且不加载

实现思路:监听触底事件

微信小程序

// 微信小程序的Page里面有onReachBottom()方法可以监听用户上拉触底事件
Page({
    onReachBottom(){
        /*开始请求加载图片*/
    }
})
// JSON文件
{
    "onReachBottomDistance": 50 // 页面上拉触底事件触发时距页面底部距离,单位为px
}
复制代码

Web 端

// html5 + vue 实现监听用户上拉触底事件
mounted () {
    window.onscroll = function(){
        var scrollTop = document.documentElement.scrollTop //当前屏幕顶部到滚动条顶部的距离
        var clientHeight = document.documentElement.clientHeight //屏幕可视区的高度
        var scrollHeight = document.documentElement.scrollHeight //滚动条的总高度
        if(scrollTop + windowHeight + 50 == scrollHeight){ 
            /*开始请求加载图片,可以先预留50px出来*/
        } 
    }
}
复制代码

6. 使用 CDN 加速

关于CDN加速的详细内容见 浏览器系列 — CDN加速

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享