定义
Start Render,顾名思义指的是浏览器开始渲染的时间,从用户角度出发则可以定义为用户在页面上看到的第一个内容的时间。
用户体验
该时间决定着用户对页面的第一体验时机,如果时间越短给用户的体验则是页面速度越快,这样用户等待其余内容展现的耐心也会更大一些。如果时间过长,则用户会在长时间内面对的都是一个空白的页面,这对用户的耐心将是一个考验。总的来说,Start Render时间是越短越好,而且是非常关键的指标。
影响因素
要想知道Start Render时间受哪些因素的影响,首先要知道这个时间是怎么计算的。归纳一下,大概可以用以下这个公式来表示:
Time To Start Render = TTFB + TTDD + TTHE
其中:
TTFB(Time To First Byte):发起请求到服务器返回数据的时间
TTDD(Time To Document Download):从服务器加载HTML文档的时间
TTHE(Time To Head End):HTML文档头部解析完成所需要的时间
通过以上公式可以看到Start Render主要受以下因素影响(开发人员可控):
(1) 服务器响应时间
(2) HTML文档的大小
(3) Head中资源使用情况
监控方式
在Firefox下,可以通过在window上注册"MozAfterPaint"事件来计算浏览器开始渲染的时间,具体的实现可以参考FF的官方文档。在其他没有实现类似接口的浏览器则需要自己处理,根据Start Render的定义可以知道,当开始渲染时用户是可以在浏览器中看见内容的,而有内容的时候document.body.offsetHeight应该是大于0的,因此根据这一特点使用timer来检查。
- (function(){
- if(/Firefox/.test(navigator.userAgent)){
- window.addEventListener("MozAfterPaint", function(){
- window.removeEventListener("MozAfterPaint",
- arguments.callee, false);
- window.pmc_start_render_time = new Date()*1;
- alert(1);
- }, false);
- }
- else{
- if(document.body && document.body.offsetHeight > 0 ){
- window.pmc_start_render_time = new Date()*1;
- alert(2);
- return;
- }
- setTimeout(arguments.callee,30);
- }
- })();
经过测试,使用timer模拟的与FF下MozAfterPaint得到的结果基本上一致,包括在不同位置引用Javascript对Start Render的影响。测试>>
优化方法
从Start Render的影响因素着手一一分析:
(1) 减少服务器响应时间
主要是为了减少TTFB,一方面需要尽可能减少服务器处理请求的时间;另一个方面则可以使用flush方法,使得服务器生成的内容可以尽早的输出到客户端,这也是Yahoo众多优化原则之一,不过Yahoo的建议是在</head>标签之后flush,也就是将整个HEAD部分提前输出,好处是可以让HEAD中的CSS、Javascript资源提前开始加载,为之后的内容渲染提前准备。但同时并不能很好的减少Start Render时间,因为只是输出了HEAD,此时页面依旧是一片空白。更近一步的做法是将BODY中的部分内容提前输出,通常可以将页面中的通用头部提前输出。但是在BODY中flush需要注意的是:如果在BODY中未闭合的标签中flush,则浏览器并不会提前解析,而是等到所有内容都收到后才开始。
- <html>
- <head>
- <body>
- <div id="doc">
- <div id="hd">
- <!--在这里flush浏览器并不会立即渲染-->
- </div>
- </body>
- </html>
更合理的flush位置
- <html>
- <head>
- <body>
- <div id="hd">
- </div>
- <?php flush() ?>
- </body>
- </html>
(2) 减小HTML文档体积
主要方法是对HTML文档进行压缩,具体可以参考这篇文章《HTML优化》。
(3) 减少Head中资源使用
主要是为了减少Time To Head End。在Head中消耗时间比较长的主要是外链Javascript以及执行时间较长的内联Javascript。这其中,外链Javascript又是最大的影响因素,因为在加载和执行的过程中会阻塞整个浏览器的渲染。
(a) 应该尽可能的减少Head中外链Javascript个数,如果允许可以只在Head中放CSS资源,而Javascript可以放到首个渲染元素之后。
(b) 如果Head有执行时间比较长的内联脚本,则可以考虑使用异步方式执行。
(c) 如果有隐藏的HTML内容诸如一些浮动层的内容,应该尽量放在首次渲染元素之后,可以减少解析时间。