浏览器是如何工作的?——How Browsers Work:Behind the Scenes of Modern Web Browsers
浏览器是如何工作的?——How Browsers Work:Behind the Scenes of Modern Web Browsers
——Arthur 2011.11.12
实验室例会讲Paper,上周让我做的Presentation,题目就是这篇文章:How Browsers Work:Behind the Scenes of Modern Web Browsers (http://www.html5rocks.com/en/tutorials/internals/howbrowserswork/)
网页看起来不算很多,但打印下来足有40+页。纯英文,开头部分看着还行,逻辑还比较清晰,但越看到后面越觉得混乱。强迫自己做了一下Paper的框架,将主干结构列出,同时加入讲时需要添加的小例子。不充满血肉,只列出骨架。做完这件事之后,顿觉清爽无比。整篇文章就可以像鱼提起来,抖一下,骨骼就显露出来。对帮助理解文章非常有效果。
本想做成思维导图的,但虽说列框架,自己在本子上也写了大概六大页,图不好做,做了贴出来也看不清,所以还是只把框架贴上来。竖向分类时的表现力有些不足,但结构还算很清晰。
有人翻译了原文,本次框架里的中文很多是从翻译中copy过来的,有些拿不准的部分再去翻原文看。译文地址:http://blog.csdn.net/zzzaquarius/article/details/6532299
HTML5 Rocks
How Browsers Work:Behind the Scenes of Modern Web Browsers
CH 1 简介
涉及浏览器:Firefox Chrome Safari(partly open source)
主要功能:展现网页资源 HTML CSS标准 (W3C维护)
UI:地址栏、前进后退、书签、刷新、停止、主页
High Level Structure
CH2 渲染引擎 Rendering Engine
Gecko:Firefox
Webkit:Chrome Safari
Main Flow:先构建DOM Tree→在构建渲染Tree→再据此布局(layout)→绘制(paint)(注:DOM--document object model 文档对象模型)
Webkit、Gecko的rendering main flow图示见figure 3、4
CH3 解析 Parsing
3.1 Parsing-general
解析文件就是把它翻译成为可理解的代码结构。例:2+3-1
解析分两个子进程:1.lexical analysis 词汇分析:breaking input into tokens 2.syntax analysis 语法分析
Document→Lexical Analysis→Syntax Analysis→Parse Tree
解析过程是迭代循环的。
翻译/转换:经常在解析完毕后,需要翻译成机器代码文件
Source Code→Parsing→Parse Tree→Translation→Machine Code
解析示例:2+3-1
Parser类型:1.top down parsers 从语法的高层结构开始 2.bottom up parsers 从语法的底层结构开始
3.2 Html Parser(HTML解析)
不是context free grammar(与上下文无关的语法) 更宽容(forgiving),允许犯错(注:这是HTML流行起来的原因,也是后面提到Error Toleracne(出错忍耐)的原因)
HTML定义:DTD(Document Type Definition)格式。定义元素、属性、层级
DOM:文档对象模型(注:重点部分)
解析树(parse tree)是由DOM元素及属性节点组成。DOM是html文档的对象表示,作为html元素的外部接口供javascript等调用。
DOM和标签基本是一一对应关系。示例图figure 8
解析算法:
HTML不能用一般的top down或bottom up parsers解析(原因3点)
因此使用定制的custom parser进行解析。
其解析规则在HTML5中规定,包含两个部分:符号化(tokenization--即为lexical analysis)、构建树(tree construction)
The tokenization algorithm:略(3.2.6)
The Tree construction algorithm:略(3.2.7)
出错忍耐(Error Tolerance):
浏览器fix网页中的“无效语法”等错误。(因为HTML语言很forgiving——前有提到)
HTML5中规定了需要注意的错误情形,4种。举例:webkit
3.3 CSS解析
CSS:Casading Style Sheets 层叠样式表
context free grammar 与上下文无关的语法,是一种将表示样式应用到标记的系统
定义了lexical grammar(defined by regular expressions--正则表达式)和syntax grammar(Described in BNF--Backus-Naur Form 巴科斯-诺克范式)
举例:webkit CSS解析图 figure 12
3.4 处理脚本(Script)和样式表(Style Sheets)的顺序
Web的模式是同步的。
Webkit和Firefox做了优化,进行预解析脚本。
CH4 构造渲染树 Render Tree Construction
DOM树构建完成后,浏览器开始构建渲染树(Render tree)
渲染树按照显示顺序包含视觉元素,是文档的视觉表示。
构建渲染树的目的是以正确的顺序绘制(Painting)内容。
Firefox中叫渲染树中元素为“Frame”(帧)。
Webkit中叫渲染树中元素为“Render”或“Render Object”。(一个Render知道怎样布局(layout)和绘制(paint)它自己和其子节点)
Render Tree和DOM Tree的关系:(注:重点部分)
对应,但非一一对应。
不可见的DOM元素不会被插入渲染树。
一些DOM元素对应几个可见对象。如select元素对应显示区域、下拉列表和按钮三个对象。
一些渲染对象和所对应的DOM接电不在树上相同的位置。
图示对应关系:
构建树的流程:
Firefox:registered as a listener for DOM updates
Webkit:teh process fo resolving the style and creating a render is called "attachment"
样式计算 Style Computation
构建渲染树需计算每一个渲染对象的视觉属性。
计算样式的困难,3点:
1.样式数据过大
2.寻找元素对应规则易引起性能问题(若不优化的话)
3.应用规则设计复杂的级联
浏览器怎么处理这些问题:(注:以下这几个部分很长)
共享样式数据--4.3.1
Firefox规则树--4.3.2
结构化
使用规则树计算样式上下文
对规则进行处理以简化匹配流程--4.3.3
以正确的级联顺序应用规则--4.3.4
样式表的级联顺序
Spectify
对规则排序
逐步处理:Webkit
CH5 布局 Layout
计算渲染器的位置、大小等信息,称为Layout(布局--Webkit)或Reflow(回流--Gecko)。
布局一般按照从左到右、从上到下的顺序。有例外:html tables
布局是迭代过程,从根渲染器(Root Render)开始。根渲染器位置为(0,0),大小为浏览器窗口的可见部分。
Dirty Bit系统
避免为每个小变化而全部重新布局
将变动的renderer和其children标记为dirty:需要重新布局
有两个标识:1.dirty 2.Children are dirty:render本身可能OK,但至少有一个孩子(children)需要重新布局
全局和增量布局
全局:1.全局样式变动,如字号改变。 2.窗口resize。
增量:仅dirty renderer重新布局。是异步触发。
异步和同步布局
同步:1.全局layout一般均为同步触发。 2.脚本请求信息时,如“offsetHeight”
异步:增量layout
优化
当layout因resize或者渲染位置改变(而非大小改变)触发时,渲染对象大小会从缓存中读取,而不会重新计算。
若子树改变,则layout并不从根开始。如:将文本插入文本域。
Layout过程
Layout一般有以下四个部分。(略)
宽度计算
渲染对象的宽度使用容器的宽度、渲染对象样式中的宽度、margin和borders等进行计算。
举例:Webkit中:<div class= "Width:30%" />
1.容器宽度是容器的可用宽度和0中的最大值,即:
contentWidth = clientWidth() - paddingLeft() - paddingRight()
其中,clientWidth表示对象内部大小,不含border和scrollbar。
2.元素的宽度是指样式属性Width的值(本例中Width为30%);
3.加上水平方向上的borders和paddings(填充区域)。
经此3步之后,得到的是“prefered width”,还要与maximum width和minimum width比较,以保证最终宽度结果在二者之间。
折行 Line Breaking
折行时layout创建额外的渲染对象并调用他们的layout。
CH6 绘制 Painting
和布局一样,绘制也分为全局和增量:
全局:略
增量:部分渲染对象改变,但不影响整个树,仅使其在屏幕上对应的矩形区域无效。
使OS将其视作“dirty region”,并产生新的“paint event”。
Chrome中,由于renderer并非在主线程中,由Chrome模仿OS产生“paint event”
绘制顺序
和元素在栈中的存储顺序相同
背景颜色→背景图片→border→children→outline
重绘时的优化
Firefox显示列表:
Firefox读取渲染树并为绘制矩形创建了一个显示列表,该表以正确绘制顺序包含着矩形相关的渲染对象。这样,重绘时可只需查找一次树,不需多次查找。
Firefox优化:不添加会被隐藏的元素。如元素完全在其他不透明元素下。
Webkit矩形存储:
重绘前,webkit讲旧的矩形保存为位图(bitmap),然后只画新旧矩形的差集。
CH7 动态变化 Dynamic Changes
浏览器总是试着以最小的动作响应一个变化。
一个元素颜色变化 → 该元素重绘;
一个元素位置变化 → 该元素、子元素和相关元素重绘;
添加DOM数 → 该节点和相关节点重绘;
主要变化(字号改变等) → 整体的布局和重绘
CH8 渲染引擎的线程 The Rendering Engine's Threads
渲染引擎是单线程的。
Firefox Safari:浏览器主线程
Chrome:tab主线程
事件循环:
浏览器主线程是一个事件循环。它被设计为无限循环以保持执行过程的可用,等待时间(如Layout或Paint事件)并执行它们。 例:Firefox主要事件循环代码: while(!mExiting)NS_ProcessNextEvent(thread);
CH9 CSS2可视模型
画布(Canvas):
CSS2规定Canvas用来描述格式化的结构所渲染的空间——浏览器绘制内容的地方。
CSS盒模型:
包括:内容区域(必有。如图片、文本等)及可选的四周的padding、border和margin区域。如图:
Box布局的方式由:box类型、大小、定位策略和扩展信息(如图片大小或屏幕尺寸)决定。
定位策略,三种:
normal:与DOM树,渲染树中的位置一致;
float:先正常布局,再尽可能向左或右移动;
absolute:与DOM树中位置无关。
Box类型:
1.Block Box
2.Inline Box
定位(Positioning)
1.Relative
2.Floats
3.Absolute或Fixed
层级显示 Layered Representation
由CSS属性当中的z-index指定,即在z轴上的位置。z值越大,越靠前显示。