前端性能优化 —— 文档在浏览器中的加载和渲染

 

文档载入顺序如下:

地址栏输入url,浏览器下载html文档后开始解析:(参考链接:http://www.cnblogs.com/Peng2014/p/4687218.html)

1:首先形成dom tree  和 render  tree。

1:在<head>里面发现了link,则浏览器会加载css样式文件,这个过程是异步的,即发起请求后,不会影响下面文件的请求加载和渲染。比如若存在多个link,则这几个link会同时发起请求,这是多线程并行的。(当然多个css文件可以合并为一个文件来减少http请求个数,缩短相应时间

2:  接着解析器开始解析body部分,此时css样式已经准备就绪,开始渲染节点。(所以css文件应该放在body的前面来加载,这样可以减少dom节点渲染成本

3:浏览器在代码中发现一个 <img> 标签引用了一张图片,向服务器发出请求此时浏览器不会等到图片下载完,而是继续渲染后面的代码;和css加载一样    (图片文件合并,减少HTTP请求)

4.  服务器返回图片文件,由于图片占用了一定面积,影响了后面段落的排布,因此浏览器需要回过头来重新渲染这部分代码;   (最好图片都设置尺寸,避免重新渲染

6.  浏览器发现了一个包含一行 JavaScript 代码的 <script> 标签,会立即运行该js代码; 此时阻止了渲染进程    (script最好放置页面最下面,让页面样式先呈现出来) 

7.  js脚本执行了语句,它令浏览器隐藏掉代码中的某个 <div>,突然就少了一个元素,浏览器不得不重新渲染这部分代码;   (页面初始化样式不要使用js控制

8. 遇到<script src="" >后加载js文件,此时阻断下面的渲染进程,等js文件加载并执行完后再继续下面的渲染流程。<所以script的请求要放在body后面>

9.  用户点了一下界面中的“换肤”按钮,JavaScript 让浏览器换了一下 <link> 标签的 CSS 路径;

10.  浏览器召集了在座的各位 <div><span><ul><li> 们,“大伙儿收拾收拾行李,咱得重新来过……”,浏览器向服务器请求了新的CSS文件,重新渲染页面。

 

文档又是怎样渲染出图像呈现在界面上呢?(原文链接:http://www.iteye.com/news/27795



从上面这个图中,我们可以看到那么几个事: 

1)浏览器会解析三个东西: 

  • 一个是HTML/SVG/XHTML,事实上,Webkit有三个C++的类对应这三类文档。解析这三种文件会产生一个DOM Tree。
  • CSS,解析CSS会产生CSS规则树。
  • Javascript,脚本,主要是通过DOM API和CSSOM API来操作DOM Tree和CSS Rule Tree.

2) 解析完成后,浏览器引擎会通过DOM Tree 和 CSS Rule Tree 来构造 Rendering Tree。注意: 

  • Rendering Tree 渲染树并不等同于DOM树,因为一些像Header或display:none的东西就没必要放在渲染树中了。
  • CSS 的 Rule Tree主要是为了完成匹配并把CSS Rule附加上Rendering Tree上的每个Element。也就是DOM结点。也就是所谓的Frame。
  • 然后,计算每个Frame(也就是每个Element)的位置,这又叫layout和reflow过程。(这两个过程会单独拿出来写)

3)最后通过调用操作系统Native GUI的API绘制。 

 

那么CSS Rule Tree 又是如何 结合DOM  Tree  形成 Rendering Tree 的呢?

CSS解析 

CSS的解析大概是下面这个样子(下面主要说的是Gecko也就是Firefox的玩法),假设我们有下面的HTML文档: 

Html代码 
  1. <doc>  
  2. <title>A few quotes</title>  
  3. <para>  
  4.   Franklin said that <quote>"A penny saved is a penny earned."</quote>  
  5. </para>  
  6. <para>  
  7.   FDR said <quote>"We have nothing to fear but <span>fear itself.</span>"</quote>  
  8. </para>  
  9. </doc>  



于是DOM Tree是这个样子: 



然后我们的CSS文档是这样的: 

Css代码 
  1. /* rule 1 */ doc { display: block; text-indent: 1em; }  
  2. /* rule 2 */ title { display: block; font-size: 3em; }  
  3. /* rule 3 */ para { display: block; }  
  4. /* rule 4 */ [class="emph"] { font-style: italic; }  



于是我们的CSS Rule Tree会是这个样子: 



注意,图中的第4条规则出现了两次,一次是独立的,一次是在规则3的子结点。所以,我们可以知道,建立CSS Rule Tree是需要比照着DOM Tree来的。CSS匹配DOM Tree主要是从右到左解析CSS的Selector,好多人以为这个事会比较快,其实并不一定。关键还看我们的CSS的Selector怎么写了。 
注意:CSS匹配HTML元素是一个相当复杂和有性能问题的事情。所以,你就会在N多地方看到很多人都告诉你,DOM树要小,CSS尽量用id和class,千万不要过渡层叠下去,…… 

例如:

一个css规则:.text div span h1{}  ,

若从左到右匹配:则先找到.text的元素,然后再子节点里找div,遍历对每一个div找下面的span,若某一个div下面没有发现span,则回溯到上面下一个div继续找,这是树的深度遍历。

若从右到左匹配:则先找到所有h1元素,然后对每个元素向上追溯找到满足条件的节点,这种方法在大部分情况下比第一种要好,但我们在写css样式的时候应尽量做到如下2点:

(1)尽量用id或则class来标识元素;

(2)尽量不要用父元素套子元素过度层叠,例如:.text div span h1

 


通过这两个树,我们可以得到一个叫Style Context Tree,也就是下面这样(把CSS Rule结点Attach到DOM Tree上): 





所以,Firefox基本上来说是通过CSS 解析 生成 CSS Rule Tree,然后,通过比对DOM生成Style Context Tree,然后Firefox通过把Style Context Tree和其Render Tree(Frame Tree)关联上,就完成了。注意:Render Tree会把一些不可见的结点去除掉。而Firefox中所谓的Frame就是一个DOM结点,不要被其名字所迷惑了。

 

当Render Tree 构建好了之后浏览器就开始渲染了,接下来谈论影响渲染的两个因素reflowrepaint

 

 

           

posted @ 2017-03-14 19:36  潇洒-zhutao  阅读(1065)  评论(0编辑  收藏  举报