浏览器渲染流程

浏览器通过其渲染引擎在窗口中显示经过CSS文件格式化之后HTML文档内容和图片。了解其渲染流程应当是前端学习过程中一个非常重要的环节,惭愧的是今天才开始整理相关的知识。

<!--more-->

本文参考了这两篇文章:新式网络浏览器幕后揭秘浏览器的渲染原理简介。 经过查阅资料得知,渲染流程主要分为如下四个步骤:

  • 首先解析HTML构建DOM树,解析CSS文件构建CSS规则树(规则树只是firefox下的一个概念,就这样拿来用了);
  • 接着关联DOM树和CSS规则树,构建渲染树;
  • 然后对渲染树中的元素节点进行布局;
  • 最后绘制整个页面。

下面是关于整个流程的详细解释。

1. 解析

解析文档指的是将文档转化成有意义的结构。解析器通常将解析结构分给词法分析器和解析器两个组件来处理,分别对应词法分析与语法分析两个方面。词法分析将输入内容分解成多个有效标记,并分离无关的字符(如空格换行);语法分析是应用语言的语法规则的过程。解析是一个迭代的过程,类似于将一条英语句子翻译成中文的过程。

1.1. HTML文档解析

  • 解析顺序有自上而下与自下而上两种形式,但是由于HTML与XML不一样,HTML具有宽松的语法规范,且在解析过程中整个页面经常会发生改变,因此无法使用常规的解析技术。
  • HTML的解析分为标记化和树构建两个阶段。其中标记会对应词法分析,将解析的多个标记传递给树构建器进行处理,规范中定义的每个标记所对应的DOM元素会在树构建起接受到相应的标记时所创建,并添加到DOM树中。
  • 在解析不严格的HTML文档时如果遇见不符合XML规范的书写格式,浏览器解析器将对其进行处理并尽量使其内容显示出来。

1.2. CSS文档解析

  • 吸取了早年HTML的教训,CSS文档是上下文无关的语法,可以在各种解析器下进行正确解析。
  • webkit采用的是自下而上的解析器,而firefox采用的是自上而下的解析器。这两种解析器都会将CSS文件解析成stylesheet对象,每个对象都包含对应的CSS规则。

2. 渲染树

这是由可视化元素按照其显示顺序组成的树,即文档的可视化表示,其作用是使浏览器按照正确的顺序绘制内容。 渲染树中的每个元素都代表一个矩形的区域,通常对应相关节点的CSS框(是包含块吗?),包含了宽高位置等几何信息。渲染树中的元素与DOM树中的元素相对应,但并非一一对应,非可视化的DOM元素并不会插入渲染树中(如head元素或display:none的元素)。

  • 构建渲染树时,需要通过计算每一个渲染树元素的样式属性来计算他的可视化属性。在计算某个特定元素的样式上下文时,首先计算规则树中的对应路径,并沿此路径应用CSS规则,在新的样式上下文中填充结构。
  • 如果不进行优化,则在计算过程中会造成很大的性能问题。为每一个选择器对应的元素节点遍历整个规则列表来寻找匹配规则是一项十分浩大的工程,因此,选择器的嵌套与组合十分重要。
  • 在样式表解析完成之后,浏览器会根据选择器将CSS规则加到某个哈希表中,这些哈希表中的选择器各不相同,包括ID,类,标签选择器等。这种处理会大大简化匹配规则。
  • 在某个元素节点上同时应用多个重复的样式时会根据选择器的权重值进行排序,并使用优先级高的样式。

3. 布局

元素节点在添加至渲染树的时候并不包含位置和大小等几何信息,计算这些值得过程就称为布局或重排。 HTML采用基于流的布局模型,因此处于流中靠后位置的元素不会影响到位置靠前的元素的几何特性。布局分为整体布局和增量布局两种:前者需要对整个页面进行重新布局,后者对标记了dirty的所有元素进行重新布局。dirty是为了避免一个细小的改动导致整个页面进行重新布局,而采用了的一种处理系统,如果渲染树中的某个元素发生了更改,或者其自身及后代标记了dirty,则表示需要重新布局。 布局有两个很重要的概念,Repaint和Reflow。

  • Repaint表示页面上某个元素的的非定位样式需要重新绘制(比如利用JS改变了元素节点的背景颜色,此时不需要重新布局);
  • Reflow表示元素节点的几何尺寸发生了变化,此时需要重新计算并构建渲染树(即此时需要重新布局); 需要注意的是Repaint和Reflow可能同时发生在同一个元素节点上。

reflow和repaint可能会严重影响性能,因此需要尽可能的减少reflow和repaint操作,下面是几条原则:

  • 不要一条一条地修改DOM的样式,如果修改的样式过多可以将样式统一在某个类中,然后直接更改元素节点的className;
  • 使用临时变量保存DOM节点,而不是每次都直接对DOM节点进行操作(减少元素节点的读写),在JS性能与浏览器性能方面都能得到一些优化;
  • 尽可能修改层级比较低的DOM,缩小操作的影响范围;
  • 放弃使用table进行布局,一个很小的改动都会造成整个table的重新布局

4. 绘制

在绘制阶段,系统会遍历整个渲染树,并调用API将渲染树的整个内容显示在屏幕上,这里涉及到操作系统原声GUI的API,暂时还没有深入。

HTML5自定义属性 JavaScript中的继承方式