日期:2014-04-29  浏览次数:23179 次

文章简介:我关注JS和CSS的重点也是如何能够更快地下载图片。图片是用户可以直观看到的。他们并不会关注JS和CSS。确实,JS和CSS会影响图片内容的展示,尤其是会影响图片的展示方式(比如图片轮播,CSS背景图和媒体查询)。但是我认为JS和CSS只是展示图片的方式。在页面加载的过程

我的大部分性能优化工作都集中在JavaScript和CSS上,从早期的Move Scripts to the Bottom和Put Stylesheets at the Top规则。为了强调这些规则的重要性,我甚至说过,“JS和CSS是页面上最重要的部分”。

几个月后,我意识到这是错误的。图片才是页面上最重要的部分。

我关注JS和CSS的重点也是如何能够更快地下载图片。图片是用户可以直观看到的。他们并不会关注JS和CSS。确实,JS和CSS会影响图片内容的展示,尤其是会影响图片的展示方式(比如图片轮播,CSS背景图和媒体查询)。但是我认为JS和CSS只是展示图片的方式。在页面加载的过程中,应当先让图片和文字先展示,而不是试图保证JS和CSS更快下载完成。

我优化JS和CSS的目的就是让页面尽快渲染。

开始渲染的时间过迟

伴着关注渲染时间的念头,我查询了HTTP Archive来了解我们的页面开始渲染的时间。下面是一些衡量的数值:

  • TTFB,第一个HTML文档数据包到达的时间
  • 开始渲染的时间
  • 页面onload触发的时间

从世界最快的30万个地址的测量值中,我提取出其中的50%和90%部分。如下面展示的一样,在页面加载的前三分之一段时间内,没有任何渲染动作。

表格 1. 页面加载过程中的各个时间点
  TTFB 开始渲染 onload
50th percentile 610 ms 2227 ms 6229 ms
90th percentile 1780 ms 5112 ms 15969 ms

预加载

页面等待渲染的时间是整个页面加载时间的三分之一,这个事实让人出乎意料。HTTP Archive上的数据说明,页面花费了32%到36%的时间来等待渲染开始。但是只需要10%的时间来获取第一个字节。因此,浏览器在22%到26%的时间段内,虽然已经接受到了数据,但是却不做任何渲染。在这段时间内浏览器通常都是在下载解析脚本和样式—这两者都会阻碍页面的渲染。

曾经,浏览器在这个时间段内(从接受到第一个字节到渲染开始)是处于空闲状态的。这是因为旧的浏览器中,一个脚本的下载会阻塞其他所有的资源的下载,比如IE6&7。浏览器厂商意识到虽然浏览器需要等待脚本下载执行完成后才能构建DOM,但是没有理由阻塞页面其他资源的并行下载。在2009年的IE8之后,浏览器预加载其他资源的请求。研究表明,预加载让页面加载速度快了20%。今天,所有主流浏览器都支持预加载。在这些浏览器数据中,我展示了每个主流浏览器最早支持预加载的版本。

(顺便说一句,我认为预加载是最有效的性能提升方式。设想现在的浏览器中脚本下载会阻塞其他资源,面对页面上如此庞大的脚本数量,页面的性能会糟糕到哪个程度)

预加载和响应式图片

这时我们又要回到 Jason Grigsby的一条tweet:

我不得不承认一点。我试图推进响应式图片,并且越来越倾向于鼓励开发者来使用JS阻止预加载。

Jason指的“响应式图片”是一项技术,使用脚本来生成图片。通常这个技术用于实现图片对分辨率的适应。一个例子是Picturefill。当你将“预加载”和“响应式图片”合起来思考——预加载会提前加载图片的SRC,但是响应式图片技术通常又没有SRC,或者只是有一个1×1的替代图片。这两项技术之间有冲突。下面有一些权衡:

  • 不要使用响应式图片,这样浏览器就可以利用预加载尽快下载图片,但是图片可能会比需要的尺寸大很多,而且会耗费更长的时间来下载(耗费更多的流量)
  • 使用响应式图片,由于没有利用预加载,则意味着图片会在脚本下载执行后下载,这个时候IMG标签都已经创建好了。

接着Jason在后一条tweet中说:

让我觉得不舒服的是,大部分结论都没有经过测试。只是一些理论,而不是数据。

我并没有数据来比较这两个方式,但是HTTP Archive中开始渲染的时间占总加载时间的三分之一也说明了一些问题。似乎渲染确实被脚本阻塞了,也就是说IMG标签还没有被创建。那么在1/3点后的时间里,IMG标签会被解析,然后JS和CSS才会执行并开始下载需要的图片。

我认为,在页面加载过程中初始化图片请求太晚了,并且相对使用预加载后的效果,页面的渲染时间确实被推迟了。再次声明,我没有数据来对比这两项技术。同时,我也不确定在markup技术的响应式图片中使用预加载会有怎样的改观。(Jason有篇博客文章有相关的内容,The real conflict behind <picture> and @srcset)

理想情况下,我们利用markup解决了预加载和响应式图片之间的冲突问题。直到那时,我依然担心这样的技术在开发社区中大量使用会让响应式图片付出预加载失效的代价。我希望浏览器可以增强预加载的效果,那么现在和未来里网站就能够充分利用预加载的功能。