对优化网页图片加载有如下6种方案:
- 图片压缩
- 先加载压缩图片,再加载高清大图,加载完毕后代替掉
- 使用base64、css、canvas代替简单图片
- 图片预加载
- 图片懒加载
- 使用 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加速