星空网 > 软件开发 > 网页设计

【转】浏览器的渲染原理简介

How Browsers Work 这篇文章把浏览器的很多细节讲的很细,也有中文的翻译版本,现在转载的这篇是陈皓写的,目的的为了能在上班途中,或是坐马桶时就能读完,并能从中学会一些能用在工作上的东西。

 

浏览器工作大流程

先看个图

【转】浏览器的渲染原理简介

从图中,可以看到:

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 Tree,因为一些像 Header 或 display:none 的东西就没必要放在渲染树中。* CSS 的Rule Tree 主要是为了完成匹配并把CSS Rule附加上 Rendering Tree 上的每个 Element,也就是 DOM 节点,也就是所谓的 Frame。* 然后,计算每个 Frame(也就是每个Element)的位置,这又叫 layout 和 reflow 过程。

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

 

DOM 解析

HTML 的 DOM Tree解析如下:

<html><html><head>  <title>Web page parsing</title></head><body>  <div>    <h1>Web page parsing</h1>    <p>This is an example Web page.</p>  </div></body></html>

上面这段HTML 会解析成这样:

【转】浏览器的渲染原理简介

下面是另一个有 SVG 标签的情况:

【转】浏览器的渲染原理简介

 

CSS 解析

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

<doc><title>A few quotes</title><para class="emph"> Franklin said that <quote>"A penny saved is a penny earned."</quote></para><para> FDR said <quote>"We have nothing to fear but <span class="emph">fear itself.</span>"</quote></para></doc>

于是DOM Tree 是这个样子:

【转】浏览器的渲染原理简介

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

/* rule 1 */ doc { display: block; text-indent: 1em; }/* rule 2 */ title { display: block; font-size: 3em; }/* rule 3 */ para { display: block; }/* rule 4 */ [] { font-style: italic; }

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

【转】浏览器的渲染原理简介

图中的第四条规则出现了两次,一次是独立的,一次是在规则3的子节点。所以,可以知道建立CSS Rule Tree是需要比照着 DOM Tree来的。CSS 匹配DOM Tree 主要是从右到左解析CSS 的 Selector。

注意:CSS 匹配HTML 元素是一个相当复杂和有性能问题的事情。所以你可能会在N多地方看到很多人都告诉你,DOM 树要小,CSS 尽量用id 和 class,千万不要过渡层叠下去。

通过这两个树,我们可以得到一个叫做 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节点。

 【转】浏览器的渲染原理简介

注:Webkit 不像Firefox 要用两个树来干这个,Webkit 也有 Style对象,它直接把这个 Style对象存在了相应的 DOM节点上了。

 

渲染

渲染的流程基本上如下(黄色的四个步骤):

1.计算CSS样式

2.构建Render Tree

3.Layout - 定位坐标和大小,是否换行,各种position,overflow,z-index属性等等

4.正式开画

【转】浏览器的渲染原理简介

注意:上图流程中很多连接线,这表示了 JavaScript动态修改了DOM 属性或CSS 属性,有些改变会导致重置 Layout,而不如那些指向天上的箭头的改变则不会,比如修改后的CSS Rule没有被匹配到等等。

 

这里重要说说两个概念,一个是  Repaint,一个是 Reflow,这两个不是一回事。

* Reflow —— 屏幕一部分要重画,比如某个CSS的背景色变了。但是元素的几何尺寸没有变。
* Repaint —— 意味着元件的几何尺寸变了,我们需要重新验证并计算 Render Tree。是Render Tree的一部分或全部发生了变化。这就是Reflow,或者说是Layout (HTML 使用的是 flow based layout,也就是流式布局,所以如果某元件的几何尺寸发生了变化,需要重新布局,也就是 Reflow)。reflow 会从 <html> 这个root frame 开始递归往下,依此计算所有节点的几何尺寸和位置。在 reflow 的过程中,可能会增加一些 frame,比如一个文本字符串必须被包装起来。

 

下面是一个打开 Wikipedia 时的Layout/Reflow 的视频(注:HTML 在初始化时也会做一次 reflow,叫 intial reflow),你可以感受下:

 

Reflow 的成本比Repaint的成本高很多。DOM Tree里的每个节点都会有 reflow 方法,一个节点的 reflow 很有可能导致子节点,甚至父节点以及同级节点的 reflow。在一些高性能的电脑上也许还没什么,但是如果 reflow 发生在一些手机上,那么这个过程是非常痛苦和耗电的。

 

所以,下面这些动作有很大可能是成本比较高的:

* 当你增加、删除、修改DOM节点时,会导致Reflow 或Repaint

* 当你移动DOM位置,或是搞个动画的时候

* 当你修改CSS样式的时候

* 当你Resize 窗口的时候(移动端没有这个问题),或是滚动的时候

* 当你修改网页的默认字体的时候

注:display:none 会触发 reflow,而 visibility:hidden 只会触发 repaint,因为没有发现位置变化

 

关于滚动,通常来说如果在滚屏的时候,我们的页面上的所有的图像都会跟着滚动,那么性能上没有什么问题,因为我们的显卡对于这种把全屏像素往上往下移的算法是很快的。但是如果你有一个 fixed的背景图,或是有些 Element不跟着滚动,有些 Element是动画,那么这个滚动的动作对于浏览器来说会是一个相当痛苦的过程。你可以看到很多这样的网页在滚动的时候性能有多差,因为滚屏也有可能造成 reflow。

 

基本来说,reflow 有如下几个原因:

* Initail:网页初始化的时候

* Incremental:一些JavaScript在操作DOM Tree的时候

* Resize:某些元件的尺寸发生变化时

* Style Change:CSS属性发生了变化

* Dirty:几个 Incremental 的reflow 发生在同一个 frame 的子树上

 

我们来看一个示例:

var bstyle = document.body.style; // cache bstyle.padding = "20px"; // reflow, repaintbstyle.border = "10px solid red"; // 再一次的 reflow 和 repaint bstyle.color = "blue"; // repaintbstyle.backgroundColor = "#fad"; // repaint bstyle.fontSize = "2em"; // reflow, repaint // new DOM element - reflow, repaintdocument.body.appendChild(document.createTextNode('dude!'));

当然,我们的浏览器是聪明的,它不会像上面那样,每一次修改样式就会 reflow 或 repaint。一般来说,浏览器会把这样的操作积攒一批,然后做一次 reflow,这叫异步reflow 或增量异步 reflow。但是有些情况浏览器是不会这样做,比如:resize 窗口,改变了页面默认的字体等。对于这些操作,浏览器会马上进行 reflow。

 

但是有些时候,我们的脚本会阻止浏览器这么干,比如如果我们请求下面的一些 DOM值:

* offsetTop/Left/Width/Height

* scrollTop/Left/Width/Height

* clientTop/Left/Width/Height

* IE中的 getComputedStyle() 或 currentStyle

因为如果我们需要这些值,那么浏览器需要返回最新的值,而一样会会 flush出去一些样式的改变,从而造成频繁的 reflow/repaint

 

减少reflow/repaint

下面是一些Best Practices:

1) 不要一条一条的修改DOM样式。与其这样,还不如预先定义好css的class,然后修改DOM 的className

// badvar left = 10,top = 10;el.style.left = left + "px";el.style.top = top + "px"; // Goodel.className += " theclassname"; // Goodel.style.cssText += "; left: " + left + "px; top: " + top + "px;";

2) 把DOM离线后修改,如:

* 使用 documentFragment 对象在内存里操作 DOM* 先把 DOM给 display:none(有一次 reflow),然后想怎么改就怎么改,比如修改100次,然后再把它显示出来* clone 一个DOM 节点到内存里,然后想怎么改就怎么改,改完后再和在线的那个交换一下

3) 不要把DOM节点的属性值放在一个循环里或者当成循环里的变量。不然,这会导致大量的读写这个节点的属性。

4) 尽可能地修改层级比较低的DOM。当然,改变层级比较低的 DOM有可能造成大面积的reflow,但是也可能影响范围很小。

5) 为动画的HTML元件使用fixed或absolute的position。那么修改他们的CSS是不会reflow的。

6) 千万不要使用 table 布局。因为很小的改动就会造成整个 table 的重新布局。

Fixed layout, CSS 2.1 Specification

In this manner, the user agent can begin to lay out the table once the entire first row has been received. Cells in subsequent rows do not affect column widths. Any cell that has content that overflows uses the ‘overflow’ property to determine whether to clip the overflow content.

Automatic layout, CSS 2.1 Specification

This algorithm may be inefficient since it requires the user agent to have access to all the content in the table before determining the final layout and may demand more than one pass.

 

几个工具和几篇文章

有时候,你会发现在IE下,当你不知道修改了什么东西,结果CPU一下子就上到100%,然后过了好几秒钟 repaint/reflow 才完成,这种事情在IE时代时常发生。所以,我们需要一些工具来帮助我们查看我们的代码是否有什么不合适的东西。

* Chrome下,Google的 SpeedTracer 是个非常强悍的工具,能让你查看你的浏览器渲染本有多大。其实Safari 和 Chrome都可以使用开发者工具里的一个Timeline的工具。

* Firefox下基于Firebug 的叫 Firebug Paint Events 插件也不错

* IE下可以用一个叫 dynaTrace 的IE扩展

 

最后分享几篇提高浏览器性能的文章:

* Google – Web Performance Best Practices

* Yahoo – Best Practices for Speeding Up Your Web Site

* Steve Souders – 14 Rules for Faster-Loading Web Sites

 

来源: 陈皓-浏览器的渲染原理简介




原标题:【转】浏览器的渲染原理简介

关键词:浏览器

*特别声明:以上内容来自于网络收集,著作权属原作者所有,如有侵权,请联系我们: admin#shaoqun.com (#换成@)。
相关文章
我的浏览记录
最新相关资讯
海外公司注册 | 跨境电商服务平台 | 深圳旅行社 | 东南亚物流