浏览器工作原理学习笔记

浏览器工作原理学习笔记

浏览器的工作原理:新式网络浏览器幕后揭秘

How Browsers Work: Behind the scenes of modern web browsers

https://www.html5rocks.com/zh/tutorials/internals/howbrowserswork/

https://www.html5rocks.com/en/tutorials/internals/howbrowserswork/

Main components

main components

Rendering engine

Gecko(Firefox)

WebKit(Safari,Chrome and Opera)

Rendering engine basic flow

main flow

Parser–Lexer combination

Parsers usually divide the work between two components: the lexer (sometimes called tokenizer) that is responsible for breaking the input into valid tokens, and the parser that is responsible for constructing the parse tree by analyzing the document structure according to the language syntax rules.

Browsers’ error tolerance

You never get an “Invalid Syntax” error on an HTML page. Browsers fix any invalid content and go on.

处理脚本和样式表的顺序(需要知道,优化网页性能的时候用得上

按顺序执行,遇到需要网络请求的脚本,会先完成网络请求在继续执行。

脚本标注为“defer”,就不会停止文档解析。

HTML5 增加了一个选项,可将脚本标记为异步,以便由其他线程解析和执行。

WebKit 和 Firefox 都进行了预解析优化,预解析器不会修改 DOM 树,而是将这项工作交由主解析器处理;预解析器只会解析外部资源(例如外部脚本、样式表和图片)的引用。

样式表:Firefox 在样式表加载和解析的过程中,会禁止所有脚本。而对于 WebKit 而言,仅当脚本尝试访问的样式属性可能受尚未加载的样式表影响时,它才会禁止该脚本。

The render tree relation to the DOM tree

render tree

图:“viewport”在WebKit中是“RenderView”对象。

呈现器是和 DOM 元素相对应的,但并非一一对应。非可视化的 DOM 元素不会插入呈现树中,例如“head”元素。如果元素的 display 属性值为“none”,那么也不会显示在呈现树中(但是 visibility 属性值为“hidden”的元素仍会显示)。一个DOM元素也可以对应多个可视化对象,对应多个呈现器。如“select”元素。

样式计算

构建呈现树时,需要计算每一个呈现对象的可视化属性。这是通过计算每个元素的样式属性来完成的。

样式包括来自各种来源的样式表、inline 样式元素和 HTML 中的可视化属性(例如“bgcolor”属性)。其中后者将经过转化以匹配 CSS 样式属性。

样式表的来源包括浏览器的默认样式表、由网页作者提供的样式表以及由浏览器用户提供的用户样式表(浏览器允许您定义自己喜欢的样式。以 Firefox 为例,用户可以将自己喜欢的样式表放在“Firefox Profile”文件夹下)。

Fireafox规则树

为了简化样式计算,Firefox 还采用了另外两种树:规则树和样式上下文树。WebKit 也有样式对象,但它们不是保存在类似样式上下文树这样的树结构中,只是由 DOM 节点指向此类对象的相关样式。

Firefox 规则树还有助于按照正确的顺序应用属性。

style contexts

样式表层叠顺序

根据 CSS2 规范,层叠的顺序为(优先级从低到高):

  1. 浏览器声明
  2. 用户普通声明
  3. 作者普通声明
  4. 作者重要声明
  5. 用户重要声明
布局

呈现器在创建完成并添加到呈现树时,并不包含位置和大小信息。计算这些值的过程称为布局或重排。

HTML 采用基于流的布局模型,这意味着大多数情况下只要一次遍历就能计算出几何信息。处于流中靠后位置元素通常不会影响靠前位置元素的几何特征,因此布局可以按从左至右、从上至下的顺序遍历文档。但是也有例外情况,比如 HTML 表格的计算就需要不止一次的遍历。

布局是一个递归的过程。它从根呈现器(对应于 HTML 文档的 <html> 元素)开始,然后递归遍历部分或所有的框架层次结构,为每一个需要计算的呈现器计算几何信息。

Dirty 位系统

为避免对所有细小更改都进行整体布局,浏览器采用了一种“dirty 位”系统。如果某个呈现器发生了更改,或者将自身及其子代标注为“dirty”,则需要进行布局。

有两种标记:“dirty”和“children are dirty”。“children are dirty”表示尽管呈现器自身没有变化,但它至少有一个子代需要布局。

全局布局和增量布局

全局布局是指触发了整个呈现树范围的布局,触发原因可能包括:

  1. 影响所有呈现器的全局样式更改,例如字体大小更改。
  2. 屏幕大小调整。

布局可以采用增量方式,也就是只对 dirty 呈现器进行布局(这样可能存在需要进行额外布局的弊端)。
当呈现器为 dirty 时,会异步触发增量布局。例如,当来自网络的额外内容添加到 DOM 树之后,新的呈现器附加到了呈现树中。全局布局是指触发了整个呈现树范围的布局,触发原因可能包括:

异步布局和同步布局

增量布局是异步执行的。全局布局往往是同步触发的。

布局处理

布局通常具有以下模式:

  1. 父呈现器确定自己的宽度。
  2. 父呈现器依次处理子呈现器,并且:
    1. 放置子呈现器(设置 x,y 坐标)。
    2. 如果有必要,调用子呈现器的布局(如果子呈现器是 dirty 的,或者这是全局布局,或出于其他某些原因),这会计算子呈现器的高度。
  3. 父呈现器根据子呈现器的累加高度以及边距和补白的高度来设置自身高度,此值也可供父呈现器的父呈现器使用。
  4. 将其 dirty 位设置为 false。
全局绘制和增量绘制

和布局一样,绘制也分为全局(绘制整个呈现树)和增量两种。

绘制顺序

绘制的顺序其实就是元素进入堆栈样式上下文的顺序。

CSS2规范定义,块呈现器的堆栈顺序如下:

  1. 背景颜色
  2. 背景图片
  3. 边框
  4. 子代
  5. 轮廓
呈现引擎的线程

呈现引擎采用了单线程。几乎所有操作(除了网络操作)都是在单线程中进行的。

网络操作可由多个并行线程执行。并行连接数是有限的。

事件循环

浏览器的主线程是事件循环。它是一个无限循环,永远处于接受处理状态,并等待事件(如布局和绘制事件)发生,并进行处理。

CSS2 可视化模型

基础,这部分多看下原文!!