整理自 http://taligarsiel.com/Projects/howbrowserswork1.htm
https://sylvanassun.github.io/2017/10/03/2017-10-03-BrowserCriticalRenderingPath/
浏览器的结构
![](https://img.haomeiwen.com/i2969235/8781ee4283567e2c.png)
- browser engine : 查询和操作 rendering engine的接口
- rendering engine: 渲染浏览器请求的内容,比如解析html、css和显示解析后的内容
- networking :网络调用,比如http请求
- UI 后台:画基础组件,比如选项框和窗口。暴露一组接口,底层是操作系统的user interface方法。
- Javascript 解释器: 解析和执行 Javascript代码。
- 数据存: 持久层,浏览器存储各种类型的数据到硬盘上,比如cookies。
Chrome,每个tab是一个进程。
Rendering engines
Firefox :Gecko,Safari 和 Chrome:Webkit
Webkit,最初是Linux平台的rendering 引擎,后来被Apple修改为支持Mac和Windows。
主流程
![](https://img.haomeiwen.com/i2969235/c00fa8b50b578a05.png)
Webkit
![](https://img.haomeiwen.com/i2969235/19735b4652770d3e.png)
Mozilla's Gecko
![](https://img.haomeiwen.com/i2969235/c6c1bee08feba98d.png)
解析
生成语法树。
语法
解析器
![](https://img.haomeiwen.com/i2969235/86dee42bb1c9b88d.png)
词法分析: lexer/tokenizer 拆分为有效tokens
语法分析:syntaxanalysis 构建解析树/语法树
解析过程是迭代重复的。
翻译 Translation
翻译成机器语言
image.png
HTML解析器
解析HTML标签,生成解析树
-
不是一个上下文无关语法 Not a context free grammer
与XML的不同,因为HTML很包容,比如可以没有闭合标签。 -
HTML DTD
DTD: Document Type Definition
不同类型的DTD,比如 https://www.w3.org/TR/html4/strict.dtd
- DOM
Document Object Model
HTML的解析树:DOM 元素+ 属性节点。
它是HTML文档的Object presentation。
是HTML元素对外的接口。比如对Javascript。
这棵树的根节点是Document对象。
![](https://img.haomeiwen.com/i2969235/c8dc10597a1bb7cb.png)
- 解析算法
HTML不能按常规的从上往下,或者从下往上的解析。
因为,HTML的容错性;解析过程中,可能会通过JS,document.write 改变tokens。
![](https://img.haomeiwen.com/i2969235/e3a51172bcb750fa.png)
-
The tokenization 算法
image.png
-
Tree construction 算法
image.png
- 解析结束后?
开始解析“deferred”模式的脚本。
document的state设为complete。
load事件开始调用。
CSS 解析
不同于HTML,是context free grammer。
![](https://img.haomeiwen.com/i2969235/24ffb52fdd20946a.png)
scripts 解析
处理脚本和样式表的顺序
- Scirpts
The model of web是同步的。阻塞的。
脚本执行会阻塞document解析。
fetch脚本也会阻塞document解析。
defer不会。
HTML5 的 worker会重新开启一个线程解析和执行脚本。
-
Speculative parsing (不知道该怎么翻译)
Webkit和Firefox的一种优化策略。
执行脚本的时候,会并发加载css、js、image等外部资源。(networks) -
样式表
样式表不会改变DOM tree。所以不会阻塞document解析。
但是脚本可以在document解析阶段请求样式信息,如果样式还没加载和执行完成,脚本会出错。
因此,Firefox会在样式表加载执行阶段,阻塞脚本执行。Webkit只会在请求会被样式表影响到的样式属性时才阻塞脚本执行。
构造Render tree
![](https://img.haomeiwen.com/i2969235/f6e30227c3306a4b.png)
The initial containing block:Viewport (Firefox)/ RenderView(Webkit)
![](https://img.haomeiwen.com/i2969235/4a3211a921374359.png)
样式计算
计算每个元素的样式属性。
Firefox为了简单的样式计算,有两个额外的树。Rule tree 和 style context tree。
Webkit 有样式对象,但没有保存在类似style context tree的树里只有dom的节点指向相应的样式。
Firefox rule tree
![](https://img.haomeiwen.com/i2969235/95e1425d6aa647f5.png)
style context tree里包含最终的准确的值。比如算出百分比。
![](https://img.haomeiwen.com/i2969235/2771bc1e9ece3d77.png)
![](https://img.haomeiwen.com/i2969235/331a8d9e700b8354.png)
Gradual process
Webkit会设置一个标记,如果所有顶层样式没有加载完。
一旦样式表加载完,这些dom将重新计算样式。
布局Layout
Render树创建完成之后,需要得到position和size。
计算这些值被称为 Layout或者Reflow。
布局是一个循环的过程,从root开始,
Dirty bit system
页面重写标志位
两个标志:"dirty" 和"children are dirty"
Global and incremental layout
全局:比如resize,global style改变
增量:其他,只有dirty renderers才会重新布局
同步、异步布局
Asynchronous and Synchronous layout
增量的布局是异步的。
Firefox有个scheduler 批处理增量reflow commands。
Webkit有计时器执行。
脚本获取样式信息,比如offsetHeight
会导致同步的reflow。
全局布局通常是同步的。
有些可能是事件的回调会异步。
Painting
display content on the screen
和布局一样,painting也分全局和增量的。
增量:操作系统针对显示器的dirty region
生成paint事件。
Chrome的renderer在一个不同的进程,然后到主进程。
Chorme在一定程度模仿操作系统的行为。
Firefox display list
Firefox会为paint区域先遍历一遍render tree然后创建一个display list。
这样的话,paint过程只用遍历一次。而不是,先所有的背景,然后所有的图片,然后所有的边框,等等。
Webkit rectangle storage
repainting之前,webkit会将老的区域存储为bitmap。
只重绘新老的差别部分。
Dynamic changes
The rendering engine's threads
Rendering 引擎是单线程,几乎所有事情,除了network操作,都在该线程中执行。
在Firefox、Safari中是浏览器的主线程。
在Chrome中是tab进程的主线程。
Network操作是多个线程并行执行的。线程连接总数限制是2-6(不同浏览器不同)
Event loop
浏览器的主线程是个eventloop。
是一个无限的循环。
等待事件(比如layout和paint)和处理事件。
网友评论