了解html页面的渲染过程

标签: html 页面 渲染 | 发表时间:2013-01-11 01:15 | 作者:yuezk
出处:http://www.cnblogs.com/

最近在学习前端的性能优化,有必要了解一下页面的渲染流程,以便对症下药,找出性能的瓶颈所在。以下是我看到的一些东西,分享给大家。

参考: Understanding the renderer

页面的渲染有以下特点:

  • 单线程事件轮询
  • 定义明确、连续、操作有序(HTML5)
  • 分词和构建DOM树
  • 请求资源并预加载
  • 构建渲染树并绘制页面

具体来说:

当我们从网络上得到HTML的相应字节时,DOM树就开始构建了。由浏览器更新UI的线程负责。当遇到以下情况时,DOM树的构建会被阻塞:

  • HTML的响应流被阻塞在了网络中
  • 有未加载完的脚本
  • 遇到了script节点,但是此时还有未加载完的样式文件

渲染树构建自DOM树,并且会被样式文件阻塞。

由于是基于单线程的事件轮询,即使没有脚本和样式的阻塞,当这些脚本或样式被解析、执行并且应用的时候,也会阻塞页面的渲染。

一些不会阻塞页面渲染的情况:

  • 定义的defer属性和async属性的
  • 没有匹配的媒体类型的样式文件
  • 没有通过解析器插入script节点或样式节点

下面,通过一个例子来说明一下(完整的代码):

1 <html>
2 <body>
3   <link rel="stylesheet" href="example.css">
4   <div>Hi there!</div>
5   <script>
6     document.write('<script src="other.js"></scr' + 'ipt>');
7   </script>
8   <div>Hi again!</div>
9   <script src="last.js"></script>
10 </body>
11 </html>

代码很容易看明白,如果放在浏览器中打开会立即显示出想要的页面。下面,让我们用慢镜头回放的方式来看看它究竟是怎么渲染的。

1 <html>
2 <body>
3   <link rel="stylesheet" href="example.css">
4 <div>Hi there!</div>
5 <script>...

首先,解析器遇到了example.css,并将它从网络中下载下来。下载样式表的过程是耗时的,但是解析器并没有被阻塞,继续往下解析。接下来,解析器遇到script标签,但是由于样式文件没有加载下来,阻塞了该脚本的执行。解析器被阻塞住,不能继续往下解析。

渲染树也会被样式文件阻塞,所以这时候没有浏览器不会去渲染页面,换句话说,如果example.css文件下载不下来,Hi there! 是显示不出来的。

接下来,继续。。。

<html>
<body>
  <link rel="stylesheet" href="example.css">
<div>Hi there!</div>
<script>
  document.write('<script src="other.js"></scr' + 'ipt>');
</script>

一旦example.css文件加载完成,渲染树也就被构建好了。

内联的脚本执行完之后,解析器就会立即被other.js阻塞住。一旦解析器被阻塞,浏览器就会收到绘制请求,"Hi there!"也就显示在了页面上。

当other.js加载完成之后,解析器继续向下解析。。。

1 <html>
2 <body>
3 <link rel="stylesheet" href="example.css">
4   <div>Hi there!</div>
5   <script>
6     document.write('<script src="other.js"></scr' + 'ipt>');
7   </script>
8   <div>Hi again!</div>
9   <script src="last.js"></script>

解析器遇到last.js之后会被阻塞,然后浏览器收到了另一个绘制请求,"Hi again!"就显示在了页面上。最后last.js会被加载,并且会被执行。

但是,为了减缓渲染被阻塞的情况,现代的浏览器都使用了猜测预加载(speculative loading)。

在上面这种情况下,脚本和样式文件会严重阻塞页面的渲染。猜测预加载的目的就是减少这种阻塞时间。当渲染被阻塞的时候,它会做以下一些事:

  • 轻量级的HTML(或CSS)扫描器(scanner)继续在文档中扫描
  • 查找那些将来可能能够用到的资源文件的url
  • 在渲染器使用它们之前将其下载下来

但是,猜测预加载不能发现通过javascript脚本来加载的资源文件(如,document.write())。

注:所有的“现代”浏览器都支持这种方式。

回过来再看上面的例子,通过猜测预加载这种方式是怎么工作的。

1 <html>
2 <body>
3   <link rel="stylesheet" href="example.css">
4   <div>Hi there!</div>
5   <script>...

解析器返现了example.css,并从网络获取,解析器没有被阻塞,继续解析,当遇到了内联的script节点时,被阻塞住,由于样式文件没有加载完成,阻塞了脚本的执行。渲染树同样也被样式文件阻塞住,所以浏览器没有收到渲染请求,看不到任何东西。到目前为止,和刚才提到的那种方式是一样的。但是接下来就由变化了。

预加载器(Speculative loader)继续“阅读”文档,发现了last.js并视图加载它。接下来:

1 <html>
2 <body>
3   <link rel="stylesheet" href="example.css">
4   <div>Hi there!</div>
5   <script>
6     document.write('<script src="other.js"></scr' + 'ipt>');
7   </script>

一旦example.css文件加载完成,渲染树也就完成了构建,内联的脚本也可以执行,之后解析器又被other.js阻塞住。解析器被阻塞住之后,浏览器会收到第一个渲染请求,“Hi there!” 会被现实在页面上。这个步骤和刚才那种情况是一致的。然后:

1 <html>
2 <body>
3   <link rel="stylesheet" href="example.css">
4   <div>Hi there!</div>
5   <script>
6     document.write('<script src="other.js"></scr' + 'ipt>');
7   </script>
8   <div>Hi again!</div>
9   <script src="last.js"></script>

解析器发现了last.js,但是由于预加载器刚才已经把它给加载下来了,放在了浏览器的缓存里,所以last.js会被立即执行。之后,浏览器会收到渲染请求“Hi again”也被显示在了页面上。

通过前后两种情况的对比,希望大家可以对页面的渲染有一定的了解,然后再有针对性的做一些优化。晚安!

(完)^_^

本文链接

相关 [html 页面 渲染] 推荐:

了解html页面的渲染过程

- - 博客园_首页
最近在学习前端的性能优化,有必要了解一下页面的渲染流程,以便对症下药,找出性能的瓶颈所在. 以下是我看到的一些东西,分享给大家. 参考: Understanding the renderer. 定义明确、连续、操作有序(HTML5). 当我们从网络上得到HTML的相应字节时,DOM树就开始构建了.

浏览器加载和渲染html的顺序-css渲染效率的探究

- - CSDN博客互联网推荐文章
1.浏览器加载和渲染html的顺序. 1、IE下载的顺序是从上到下,渲染的顺序也是从上到下,下载和渲染是同时进行的. 2、在渲染到页面的某一部分时,其上面的所有部分都已经下载完成(并不是说所有相关联的元素都已经下载完). 3、如果遇到语义解释性的标签嵌入文件(JS脚本,CSS样式),那么此时IE的下载过程会启用单独连接进行下载.

浏览器是怎样工作的:渲染引擎,HTML解析(连载二)

- - 携程UED
渲染引擎的职责是……渲染,也就是把请求的内容显示到浏览器屏幕上. 默认情况下渲染引擎可以显示HTML,XML文档以及图片. 通过插件(浏览器扩展)它可以显示其它类型文档. 比如使用PDF viewer插件显示PDF文件. 我们会在一个专门的章节讨论插件与扩展. 在这一节我们将专注渲染引擎的主要用途——显示用CSS格式化的HTML与图片.

HTML页面实现全方位页面缓存

- - CSDN博客推荐文章
【1】服务端配置一个Filter,实现对js、css和image的缓存. 完成这一步,在服务端已经实现了对页面的缓存,但是当前情况下页面还是会每次访问服务器的,只是压力减小了. 如何让页面在一段时间内不访问服务器呢. 实现方式是对应公用的JS都放到一个页面中,别的页面包含他,在这个页面中增加页面缓存.

CSS3 Region:基于HTML和CSS3的富页面布局

- John - 前端观察
译自:CSS3 regions: Rich page layout with HTML and CSS3. 中文:CSS3 Region:基于HTML和CSS3的富页面布局. 请尊重版权,转载请注明来源,多谢. 互联网已经成为一个提供参考、教材、新闻、文章和交互应用的大宝库了. 然而,当为印刷设计内容时,一些功能显然仍然不可能或者很难使用Web标准来实现.

使用HTML与CSS3进行富页面布局

- - InfoQ cn
长久以来,复杂布局一直是印刷媒体的一个主要关注点. 出版物如杂志、报纸上固有的物理限制导致它们创造了非常复杂的流布局. 在这样的布局中,内容可以跨越多个列显示并且可以环绕在图片和表格周围进行编排. 布局需要能够在整个排版过程中随着内容添加和改变进行动态调整. Adobe正通过向W3C提案 CSS Regions Module与 CSS Exclusions Module,力图将该层次的布局控制引入到Web中.

Java实现HTML页面转PDF解决方案

- - Java - 编程语言 - ITeye博客
首先,当然是找到能够解析PDF的完美组件,. 而目前开源的组件中,Itext的确是一个First Choice,如果各位单纯是做把图片转成PDF或者自己写了Velocity或者FreeMarker模板生成了HTML是非常推荐直接用Itext来进行的. 而如果,大家像我这样已经有前人写好了HTML页面或者懒得写FreeMarker模板的话.

怪异模式(Quirks Mode)对 HTML 页面的影响

- - Web前端 - ITeye博客
怪异模式(Quirks Mode)对 HTML 页面的影响. Quirks Mode 概述. 什么是 Quirks Mode. 简单来说,Quirks Mode 就是浏览器为了兼容很早之前针对旧版本浏览器设计、并未严格遵循 W3C 标准的网页而产生的一种页面渲染模式. 由渲染引擎产生的两种文档模式.

页面架构HTML+CSS ●▽● 各种布局各种实现

- - SegmentFault 最新的文章
(1)清除浏览器默认样式. (1)项目开发初期就定义好. (2) reset.css 在引入的时候一定要放在第一位. (3)不同的产品 reset.css不一样. 3.table合并边框间距. table { border-collapse: collapse; // 合并边框 border-spacing: 0; //边框间距.

Javascript高性能动画与页面渲染

- - 极客521 | 极客521
如果你不得不使用setTimeout或者setInterval来实现动画,那么原因只能是你需要精确的控制动画. 但我认为至少在现在这个时间点,高级浏览器、甚至手机浏览器的普及程度足够让你有理由有条件在实现动画时使用更高效的方式. 页面是每一帧变化都是系统绘制出来的(GPU或者CPU). 但这种绘制又和PC游戏的绘制不同,它的最高绘制频率受限于显示器的刷新频率(而非显卡),所以大多数情况下最高的绘制频率只能是每秒60帧(frame per second,以下用fps简称),对应于显示器的60Hz.