前端图片引入方式神演算,页面里有用武之地吗
分类:计算机知识

3、比较不同网速下同步请求和合并请求的加载效率

使用上述1、2的测试demo分别在3G、4G网速条件下测试结果如下:

  • 在网络环境差的情况下,合并请求明显缩短了整个加载时间;
  • 在网络环境较好的WIFI和4G下则差别不大。
测试环境 图片直接加载 complete(单位:ms) base64合并请求 complete(单位:ms)
3G 6000 4500
4G 450 400
WIFI 320 340

图片 1

前端图片引入方式神演算

2017/01/11 · 基础技术 · 图片

原文出处: 沐洒(@Musa沐洒)   

图片 2

| 导语 本文只提供推理方式和分析方法,不保证样本及计算的精准性,慎读!!!

先阐述一下背景:

我们团队对于图片的使用方式有一个明文规定如下:

  1. 凡是需要合并雪碧图,或是编码base64的图片,均放入slice目录下对应模块目录里,gulp-postcss会统一编译处理。
  2. 直接以单图形式引入页面的图片,放在page/aaa/bbb/img目录下(aaa表示业务单元,bbb表示具体页面),使用相对路径./xxx.png直接引用。
  3. 全局复用的单图,放入common/img目录下。

目录结构大概是这个样子:

图片 3

这就是我们今天的议题。

众所周知,页面内图片的引入方式一般有这3种:雪碧图,base64内联,普通单图。(canvas,svg等非常规方式不在此次议题里),先简单分析一下三种方式的优劣势:

图片 4

嗯,大概的情况是这样的,然后我来稍微扩展解释一下:

1. base64图本身确实无法缓存,但是base64图一般是存在于css里的,那么就可以随着css被缓存而实现间接缓存,所以它的缓存属性不是“无”。说它“差”是因为并不是直接被当做图片缓存。当然如果是直接写在html里的,那就没法缓存了,这个要注意。

2. base64额外增加html/css大小并不是主要问题,问题是,因此造成的渲染堵塞有时候是致命的!而作为图片文件加载则不存在这个问题,因为图片是不会堵塞到html和css加载的,因此也不会影响首屏渲染。(当然了,你非要把img标签写在style前面那我只能说,哥,我服~~~~)

了解了三种方式的优劣势之后,对于使用场景简单归纳一下:

  1. 页面自身独有的图片,全部合并成一张雪碧图。

2. 公共模块或者公共组件,如果包含多张图片,则各自为阵合并各自的雪碧图;如果只有一两个图片,或者包含有可以被其他模块、组件、页面复用的图片,则使用灵活性好的单图模式或base64模式。

不过这种说法遗留了一个问题:例如所有页面都有的吊顶区域,假如那里有一个小图,注意,是一个喔(如果是很多的话就合并啦),这种时候是直接单图引入呢?还是base64内嵌到吊顶的css里?

好像二者都可以是吧,用单图的好处就是我在首页缓存后,逛其他页面时候就不用再加载了,当然了首页就会多一个请求;而用base64模式,会少一个图片请求,但会增加吊顶css的文件大小,从而间接增加了首页的渲染堵塞时间。好吧,又TMD陷入了纠结。。。

别急!

下面我们再对base64模式做一个简单的分析:

先明确我们对于base64图片劣势的控诉点在于,1:丫会增大原始图片文件;2:植入css之后会增大css文件大小。

做一个简单的实验,我把几个全局经常出现的小图标,用base64编码,结果:

平均增大35%

图片 5

但是!

gzip压缩后 —— 4%~40%,平均增大22%

图片 6

当然样本少是一个问题,但大概的我们还是能看出来一些端倪:base64确实会增大文件,而且即使做了gzip后增幅还是居高不下。这也是为什么我们一般不会对大图片进行base64编码的原因,假如对一张100KB的图片编码,将会增加20-30KB!这是蛮恐怖的了。但我们现在说的是小图片呀,一个小图片1KB左右,即使增大30%也就增加三百多字节而已。

我们思考的更进一步,究竟怎么样的文件大小增幅,是我们可以接受的?

一个常识,普通人的肉眼可识别的视觉暂留是50ms。而根据多年前端实战经验,对于网页渲染速度,肉眼可敏感识别的渲染时长间隔是500ms,所以一般一个css3过渡效果,transition-duration 为0.3s和0.8s才会有显著区别,而0.3s和0.5s的区别,除了号称“像素眼”的重构同学和有细节控的设计师能感知外,一般人很难明显感知。

那么因此我们是不是粗略的得出一个结论:对于首屏渲染时间的减少或增加,用户可明显感知的变化范围是50ms-500ms之间,也就是说,即便你优化做得再好,小于50ms的变化,是不会被感知的,另一方面,如果你因为某个原因增加了首屏渲染时间500ms,就会产生一个很大的感官变化。

好了,这么说来,我们能接受的文件大小增幅,所导致的首屏渲染时间增加,应该控制在500ms内。对于身处公司内网的我们而言,M/s的速度显然不用在意这些细节,500ms可以轻轻松松加载几MB的资源,就算是普通用户,现在宽带整体速度都6得飞起,500ms加载几百KB应该不成问题吧。

但是!我们不能这么想啊,做产品的会把用户当做小白,我们做开发优化是不是也应该假设用户还停留在拨号上网时代?哈哈哈,开玩笑了,这倒不至于,但我们确实可以假设用户网速很一般,100kb/s的网页加载速度,对自己够狠了吧我。

基于网速100kb/s的假设,500ms可以加载50kb的资源。。。。等等!总感觉哪里不对!

一个文件的加载,应该包含了这些个过程:

图片 7

所以我们理论上“500ms可以加载50kb的资源”,指的是download这里的速度而已,但是一个小图片从请求到渲染,需要经过请求排队,请求堵塞,等待响应,下载等众多环节。。。那么500ms我们到底能加载多大的文件呢?这个问题我真的回答不了,因为这涉及到的环境变量太多了,请求堵塞,网速抖动,浏览器版本,服务器速度,dns解析等等都有可能影响到这个结果。这。。。文章写不下去了怎么办。。。不能放弃治疗啊!那么我们干脆就更加大概一点估算好了,就假设这500ms中,只有250ms是给我们用来下载资源的,那么100kb/s的速度我们可以下载25kb的资源,嗯。。。。看起来还蛮是合理的呢。。。。

我们多找几张小图看一下timing的分布:(10kb以内)

图片 8

有没有发现一个规律?对于10kb以下的小图而言,下载时间其实几乎可以忽略不计(1%左右),而真正占用贷款的是这一次次请求经历的漫长的流程(请求排队,请求堵塞,等待响应….)

补充验证:当图片大小增加到100kb以上时,下载耗时平均是总耗时的50%不到。

经过上面一大推的推演和样本测试后,我们得到了一些相对合理的参数值,接下来要抛大招(计算公式)了!

图片 9

终于!我们拿到了我们想要的计算结果!2.6倍base64图片总大小的下载时间,是我们增加的首屏负荷。之前我们已经说了,在不影响用户感官明显变化的情况下,我们仁慈的允许多500ms的下载时间,在100kb/s的弱网条件下,最终计算出,允许内嵌的base64图片大小是20kb!20kb!20kb!这和我们刚刚大概估算的25kb很接近啊!看来有些时候计算无力的情况下估算还点靠谱的。。。

机智的我经过一系列估算后,得出了一个拙劣但相当有意义的答案!意义在于,我终于知道什么大小的图片叫做小图片啦!!!不知道这个历史性难题难倒了多少重构GG!

图片 10

好吧,别打我,我知道我的计算有点暴力。。。。

Anyway!我在文章副标题里就说了,

本文只提供推理方式和分析方法,不保证样本及计算的精准性,慎读!!!

讲真,我的切入点和分析方法应该是没有问题的对吧各位?只是这其中需要计算的数值实在涉及到太多不确定性,我表示暂时受到那么一丢丢困扰,所以就先估算之,感兴趣的同学可以按照此方法重新计算哈。

做这些蛋疼的研究,终归还是要回归到业务上的,那么我们文章开始的疑问是不是已经解决了呢?经过我们一步步的推演和深入浅出,问题基本解决了。

下面简单归纳一下不同场景所应该使用的图片引入方式:(正经脸 -_- !!!)

  • 全局通用的,非特定页面或模块独有的图片,采用单图或base64方式引入,二者区别如下:
    • 若该图片在多处使用或图片本身较大(这类图总体积大于20kb),则使用单图模式
    • 若该图片只有少数地方使用且图片本身较小(这类图总体积小于20kb),则使用base64模式
  • 公共模块/组件里的图片(假设该模块名为mod-prd)
    • 模块内有N(N>=3)个图片,则全部放入**slice/mod/prd**里,使用雪碧图模式,否则参考全局通用图片处理方式
  • 页面自身独有的图片,全部合并成一张雪碧图

装逼结束,轻喷~

2 赞 3 收藏 评论

图片 11

2、引入base64格式图片做背景图

将上面50kb大小的jpg图片转换为base64格式,加在css文件中。

关闭缓存状态下,build:80ms | complete: 280ms

图片 12
开启缓存状态下,build: 160ms | complete: 210ms

图片 13

测试环境 build(单位:ms) complete(单位:ms)
OS X+chrome 160 210
iOS+微信 35 100
OS X+Safari 9 90
Android+微信 12 150

1、原生方式直接加载多张图片

大小10~70kb共9张图片。总大小约300kb

关闭缓存:build: 300ms | complete: 310ms

图片 14
开启缓存:build: 110ms | complete: 120ms

图片 15

测试环境 build(单位:ms) complete(单位:ms)
OS X+Chrome 110 120
iOS+微信 50 100
OS X+Safari 148 150
Android+微信 50 100

如何统计?

通过Navigation Timing记录的关键时间点来统计页面完成所用的时间,并通过Chrome开发工具来跟踪细节

JavaScript

var timing = window.performance.timing timing.domLoading //浏览器开始解析 HTML 文档第一批收到的字节 timing.domInteractive // 浏览器完成解析并且所有 HTML 和 DOM 构建完毕timing.domContentLoadedEventStart //DOM 解析完成后,网页内资源加载开始的时间 timing.domContentLoadedEventEnd //DOM 解析完成后,网页内资源加载完成的时间(如 JS 脚本加载执行完毕) timing.domComplete //网页上所有资源(图片等) 下载完成,且准备就绪的时间

1
2
3
4
5
var timing = window.performance.timing
timing.domLoading //浏览器开始解析 HTML 文档第一批收到的字节
timing.domInteractive // 浏览器完成解析并且所有 HTML 和 DOM 构建完毕timing.domContentLoadedEventStart //DOM 解析完成后,网页内资源加载开始的时间
timing.domContentLoadedEventEnd //DOM 解析完成后,网页内资源加载完成的时间(如 JS 脚本加载执行完毕)
timing.domComplete //网页上所有资源(图片等) 下载完成,且准备就绪的时间

以上定义来自chrome官方文档,在其它环境下也许会有差异,从测试结果看,下面的build时间在android+微信环境中一直是0,对此可能是因为渲染机制差别,此处不做深入测试。除osx+chrome之外环境的数据仅作参考。

JavaScript

build = timing.domComplete - timing.domContentLoadedEventStart //间隔记录网页内资源加载和呈现时间。 complete = timing.domComplete - timing.domLoading //页面接收到数据开始到呈现完毕的总时间。

1
2
build = timing.domComplete - timing.domContentLoadedEventStart //间隔记录网页内资源加载和呈现时间。
complete = timing.domComplete - timing.domLoading //页面接收到数据开始到呈现完毕的总时间。

分析和小结:

base64后的的js资源达381kb,在一个线程里加载,消耗大量时间,从统计结果看,在渲染性能差异上并没有场景1那么明显。
但有缓存的情况下,页面渲染完成的速度甚至更快。
从Timeline里看到细节,解析这个近400kb的js文件对整个渲染过程造成了一定压力,不过总共40ms的解析时间是完全可以接受的。

图片 16

  1. 从html里直直接引用图片链接和base64图片对渲染性能的影响几乎没有区别,在网络条件差的情况下,合并请求却能大大提高加载效率;
  2. 直接引用至html,无法缓存,将base64后的图片资源放在js文件中管理,方便设置缓存。
  3. 有一个缺点就是图片资源base64化需要扩展构建工具来支持。

分析和小结:

在OSX+Chrome环境下,将50kb的图片base64后放入样式中,build过程拉长了约20倍,使用Timeline工具可以看到,计算样式阻塞了整个过程。

图片 17

  1. 比起直接引入图片地址,css文件中引入base64格式的图片对样式渲染的性能消耗明显,如果大量使用,会带来耗电和发热的问题,需谨慎使用。
  2. Rendering消耗的时间同css文件大小、引用次数几乎成正比(未测试其它极限情况),在网络条件优质的4G环境,50~70ms的RTT(往返时延)情况下,通常移动网络的状况会更差,对于首屏优化,合适的使用还是很值得的。
  3. 图片转成base64编码后,文档大小较原文件大了一些,而经过 gzip 后两者几乎没有区别。

使用建议

  1. 图片资源的base64编码进css文件会带来一定的性能消耗,需谨慎使用。
  2. 将图片资源编码进js文件中,管理和预加载H5应用的图片资源,合理的合并请求可以大大提高页面体验。

    1 赞 1 收藏 评论

图片 18

本文由威尼斯手机娱乐官网发布于计算机知识,转载请注明出处:前端图片引入方式神演算,页面里有用武之地吗

上一篇:深度分析HTML5在移动开发方面的发展状况,HTML5在 下一篇:没有了
猜你喜欢
热门排行
精彩图文