WEB开发面试畅谈(2)——多场景下的图片优化策略

常规策略

能不用图片就不用,透明、边框、圆角、阴影、渐变都可以用CSS实现,SVG、canvas或iconfont等在主流浏览器中都已经普遍支持,可代替图片,且体积更小更具优势。SVG可无失真无限放大缩小;Canvas可实现2D、3D动态效果等。

  • 压缩

简单压缩。使用在线图片压缩网站,使用构建工具,grunt(grunt-imagemin)、gulp(gulp-book)、webpack(url-loader)等。

  • CDN部署 & 合理缓存设置 & 多尺寸支持

CDN部署不用多说,几乎是任何图片服务的标配,要求支持 gzip 压缩。针对不同的图片类型设置不同的浏览器缓存时间(max-age),包括:用户头像、Logo、icon、文案配图等;针对不同的设备尺寸,采用不同尺寸的图片大小(PC、Mobile、Pad);针对不同的设计稿图片尺寸需求,拉取不同的图片尺寸(用户头像采用100像素,新闻类列表页可采用400像素,详情页拉取1000像素),可节省流量、缩短请求传输时间。

  • 使用Data-url/base64

在http1.x时代,为了减少小图片请求带来的损耗(主要是协议头)而将其转化为Base64编码内嵌在CSS或者HTML中。存在的问题是转换为Base64编码的体积要比原图本身大。通常我们只将小于8kb的图片转换为Base64。

  • 合并精灵图

使用构建工具将多个小图合并在一张大图上,特点是减少HTTP请求数。缺点是:“一荣俱荣,一损俱损”。一旦加载失败,所有图片都会展示失败。

  • 接入webP、sharpP等优秀图片格式,减少带宽流量,加快图片加载速度

  • 渐进增强

图片加载有逐行扫描和交错扫描,在弱网络环境下,使用交错扫描加载方式的大图会先让用户看到图片的大致轮廓,对用户更加友好。具体可在Photoshop图片导出中选择交错体验尝试。

  • 渐进增强其他方式

知名博客发布网站Medium中的图片采用了 纯色 -> 低质量拉伸图片+高斯模糊 -> 正常标准图片的加载过程。可以通过分析其代码发现,其原理是这样的:1)渲染一个div,通过对容器设置宽高使其比例和大小与最终图片的比例和大小相同,避免图片加载出来的时候导致的页面的重排;2)使用 img 标签来加载一张原图质量的 10% ~ 20%的小图。由于体积小,所以可以很快加载并显示;3)小图加载完成后使用 canvas 绘制高斯模糊透明效果覆盖在小图之上。同时请求最终要加载的大图;4)最终大图加载完成后隐藏canvas。缺点:费流量,适合WiFi和有线网络。实现稍微复杂

  • 按需加载

懒加载:需要的时候才去加载,不需要不加载。

预加载:对于即将看到的图片预拉取,比如图片查看器中,预先拉取当前图片中后2~3张。

1
2
3
4
5
6
7
8
9
10
11
常见的方式如:
// 长列表
if(document.documentElement.clientHeight > targetElement.getBoundingClientReact().top){
// load image
}

// 图片查看器
const PRELOADNUM = 3
if(index <= current + PRELOADNUM && index >= current - PRELOADNUM){
// load image
}

  • 请求失败占位图 & 重试机制

图片加载失败后需要有占位图(纯色/图片),并且有稍后自动重试的功能。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//部分代码
state={
src: http://image.xxx.com/12345.png,
retry: 0
}
render() {
return <img onError={this.onError.bind(this)} src={src} />
}
onError(e, src){
if(this.state.retry > 0) { // 仅重试一次,否则加载默认图
this.setState({ src: http://image.xxx.com/defaultImg.png })
}else {
let { src. retry } = this.state,
src += '&time=' + ~~(Math.random()*1E6);
this.setState({ src, retry: ++retry });
}
}

  • 媒体查询 & picture 标签

实验性功能详见HTML picture元素

活动页

活动H5页面的特点是具有高并发访问量。尤其是在节假日访问量飙涨的状况下,对访问量的预估对于图片优化具有非常重大的意义。我们应该怎样优化?

  • 活动页面从设计上就应该避免大量的图片展示,尽可能减少图片
  • 使用一张背景大图,避免多个图片使用绝对定位层叠
  • 如果有可能,最好使用CSS、SVG、canvas或iconfont代替图片;
  • 减少图片请求数,小图片采用base64内嵌在CSS中;
  • 采用离线包