前端性能优化,不止于前端。

PIC-BG

图片认知

无论是 Web 程序还是手机应用,图片往往比文字更能吸引用户,因为人的视线似乎总在第一眼就定位在图片上。

形成这种神奇现象的原因很简单:每个人的大脑里都住着一个”原始人”。

在原始时代,人的大脑需要处理的内容大多和图像有关。

比如,我们的祖先最关心哪里新长出来可以吃的果实,哪里有新的猎物,哪里有猛兽出没、需要避开危险。

这些重要地点和周边环境通过视觉和记忆保存在大脑里,在经历漫长的进化后,人脑逐渐进化出最适宜生存的大脑结构。

因此,人类天生擅长处理和记忆图像。

同样,在网页设计中,图片更能发挥巨大作用,有一个经典说法:一图胜千言。

所以总结图片内容呈现上有以下优点:

  • 增加可读性与趣味性,尽可能减少跳出
  • 且让文章内容充实,看起来多样化
  • 提升搜索引擎抓取收录网站
  • 提高用户的浏览体验度

图片类型

下面是我们在项目开发中几乎能接触到的图片分类。

类型解读

  • jpg
  • png
  • gif
  • svg
  • APNG
  • WebP

jpg 全名是 JPEG,JPEG 格式图片以 24位颜色存储单个位图,这是我们在开发过程中最常用的图片格式之一,这种图片的优势是可以对其进行高质量的压缩,比如我们可以将其的图片的品质由 100% 降低 60%,它的体积至少会减少 50% 以上,比如一张 100K 的图片,将其品质降低到 60% 时,它的体积会在 40-50k 之间;而且在压缩后一般我们肉眼也是不易分辨其压缩前后的变化。

png 可移植网络图形格式,这类图片我们常用来做透明和半透明的素材,这种类型的图片可以展示 256 种颜色,每一种颜色都可以做成透明;缺点是体积较大,一般运用于运营型或者商家活动页、抽奖(视觉比较好)的条件下使用。

而 png 类型又分为 png8 和 png24 两种类型。

png8 类型的图片,都最多只能展示256种颜色,所以 png8 格式更适合那些颜色比较单一的图像,例如纯色、logo、图标等;因为颜色数量少,所以图片的体积也会更小;

而 png24 类型的图片,最多可展示的颜色数量多达1600万;所以 png24 所展示的图片颜色会更丰富,图片的清晰度也会更好,图片质量更高,当然图片的大小也会相应增加,比较适合像摄影作品之类颜色比较丰富的图片。

gif 图像互换格式,一般小的 icon 图标或者动画(loading.gif)会使用到,gif 也是能展示256种颜色,但是它只支持全透明和全不透明。

svg 可缩放矢量图形,属于 XML 格式,百度地图就是使用 svg 绘制的,位图当你放大时单位面积内可视的像素点会变少,所以会失真,也就是我们常说的图片模糊,首先 svg 它是一个可以进行计算矢量图,放大和缩小的时每一个像素会根据向量重新计算,固不会失真,并且 svg 的体积很小。

APNG 即 Animated PNG,从字面上理解,这种格式的图像就是一个”会动”的PNG图像, 这个最早是由 Mozilla 的两名程序员设计出来的,当时 Mozilla 放弃了 MNG 图像格式,转而自己开发了 APNG 以存储动态多图文件,他同时具备 jpg 和 png 的优点,唯一的缺点是未被标准采纳,所以没有大规模的使用。

apng

从上图可以看出,在体积一样的情况下,APNG格式的画质相对 GIF 的画质表现更加的清晰和细腻。同时,在24位的情况,由于 PNG 容纳的颜色种类远远多出256种(实际上是1680万种颜色),所以色彩还原更加细腻、真实。

WebP 它是 Google 于2010年提出了一种新的图片压缩格式,WebP 为网络图片提供了无损和有损压缩能力,同时在有损条件下支持透明通道;无损 WebP 相比 PNG 减少26%大小,有损 WebP 在相同的结构相似性下相比 JPEG 减少 25%~34% 的大小,所以它也同时具备 jpg 和 png 的优点。

目前国内外的互联网公司几年前也开始使用,国外的有 Google、Facebook 和 ebay,国内的有淘宝、腾讯和美团等。

至于 WebP 的兼容性,基本支持 IE11+ 和主流的浏览器。

webp

图片使用

说着这么多的图片类型,我们在项目开发中,如何基于性能和用户体验的权衡来选择合适的图片类型呢?

  • 如果是颜色丰富的图片,jpg 是通用的选择。
  • 如果是较通用的动画,gif 是唯一可用的选择。
  • 如果需要清晰的显示颜色丰富的图片,png 是比较好的选择。
  • 如果是企业级应用(不考虑兼容性),可以选择 webp。

图片的加载方式

图片的加载方式主要分为小波算法、离散余弦变换算法两种,浏览器根据不同图片选择不同的渲染算法,浏览器通过文件头部读取其压缩算法那,所以更改文件后缀名也不会影响加载的方式。

小波算法

小波算法是以先变模糊后逐渐清晰的一种展现方式。

目前没有发现小波算法的图片,但是业内已经有很多人基于这个概念做了处理,比如知乎。

Wavelet-algorithm-bg

首先知乎使用了懒加载的概念,当你滑到浏览器或者 app 的可视区内含有图片时,加载一个较小的图片,他们大约会请求一张缩略的 jpg 图,实际上这是直接在代码中写了 img 标签里,浏览器会正常请求;

一旦图片加载了,它们会开始绘制一个 canvas 标签,图片的数据会传递给自定义的 blur 函数,这个函数与 StackBlur 有点相似,但不完全,设置 opacity 动画效果,同时网络开始请求原图。

等原图加载完毕后,于是区域便展示原图,此时 canvas 则会隐藏掉,这几个过程可以通过 CSS3 的 transition 属性从而让整个渐变效果更加流畅,大大的提高用户体验。

离散余弦变换算法

离散余弦变换算法,是从图片的顶部开始,逐行清晰的加载,以至整张图片完整的显示。

比如我博客的旅行记录页面,FSUX之旅行;当你第一次打开,首次加载时,图片的顶部开始,逐步清晰的加载出图片完整的形态,当然第二次加载时,会有秒开的感觉(因为我做了缓存,嘿嘿)

Discrete-cosine-bg

流行做法

CSS3

CSS3 通过提供相同的视觉效果而成为图片的“替代品”,换句话说,在进行 Web 开发时,减少多余的标签嵌套,以及图片的使用数量,意味着用户要下载的内容将会更少,页面加载也会更快。

另外,更少的图片、脚本和 图片文件让 Web 站点减少 HTTP 请求数,这是提升页面加载速度的最佳方法之一。

而使用CSS3制作图形化网站无需任何图片,极大地减少HTTP的请求数量,并且提升页面的加载速度。

当然,这取决于采用CSS3特性来代替什么技术,同样还要看如何使用 CSS3 特性。

例如 CSS3 的动画效果,能够减少对 JavaScript 和 图片的 HTTP 请求,但可能要求浏览器执行很多的工作来完成这个动画效果的渲染,这有可能导致浏览器响应缓慢,致使用户流失。因此,在使用一些复杂的特效时,大家需要考虑清楚。

不过这样的现象毕竟为数不多。其实很多CSS3技术能够在任何情况下都大幅提高页面的性能。就这一条足以让我们使用CSS3。

优势:

  • 体积减小。
  • HTTP 请求数减少。
  • ctrl + 滚轮缩放十分平滑,无锯齿。
  • 用 SCSS 写 CSS 的话,尺寸计算其实很方便。

示例:500+ Free Pure CSS Icons

CSS Sprites

CSS Sprites 其实就是把网页中一些背景图片整合到一张图片文件中,再利用 CSS 的 “background-image”,“background- repeat”,“background-position” 的组合进行背景定位,background-position 可以用数字能精确的定位出背景图片的位置。

css-sprites

优点

  • 减少图片的字节
  • 减少了 http 请求,从而大大的提高了页面的性能
  • 解决了网页设计师在图片命名上的困扰,只需对一张集合的图片上命名就可以了,不需要对每一个小元素进行命名,从而提高了网页的制作效率。
  • 更换风格方便,只需要在一张或少张图片上修改图片的颜色或样式,整个网页的风格就可以改变。维护起来更加方便。

建议

  • 不建议大图片合并
  • 建议类似图片合并

iconfont

Iconfont 指用字体文件取代图片文件,来展示图标、特殊字体等元素的一种方法。

示例:iconFont

这里以 iconfont的使用 为例

font-face 字体声明:   

     .css 文件

     @font-face {font-family: "iconfont";
       src: url('iconfont.eot'); /* IE9*/
       src: url('iconfont.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
       url('iconfont.woff') format('woff'), /* chrome, firefox */
       url('iconfont.ttf') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/
       url('iconfont.svg#iconfont') format('svg'); /* iOS 4.1- */
     }

我们可以看到,不同的浏览器调用不同的字体文件。

定义一下Iconfont 的样式:

我们可以通过字体的大小font-size和自体颜色color改变图标的大小和颜色。

      .css 文件
     .iconfont {
       font-family:"iconfont" !important;
       font-size:16px;
       color:#f00;//红色
     }
 

挑选图标对应的字体编码,应用于页面中:

    .html 文件
    
    <i class="icon iconfont">&#xe60e;</i>

优点:

  • 加载文件体积小。
  • 减少 http 请求。
  • 可以直接通过 css 的 font-size,color 修改它的大小和颜色,对于需要缩放多个尺寸的图标,是个很好的解决方案。
  • 支持一些 css3 对文字的效果,例如:阴影、旋转、透明度。
  • 兼容低版本浏览器。

前瞻性做法

响应式动态图片加载(SDK)

  • 我们需要一个默认图片
  • 屏幕分辨率的信息返回给服务器
  • 使用服务器返回的更优质的图片资源
根据不同的分辨率加载不同资源的图片(部分浏览器现已支持)
    .html 文件
    
    <picture>
      <source src="/path/to/medium-image.png" media="(min-width: 600px)">
      <source src="/path/to/large-image.png" media="(min-width: 800px)">
      <img src="/path/to/mobile-image.png" alt="image description">
    </picture >

系列文章

先占个坑,后续写完。