首页 > 代码库 > 浏览器的工作原理
浏览器的工作原理
[1]浏览器的功能:将用户选择的web资源呈现出来,需要从服务器请求资源,并将其显示在浏览器窗口中,资源的格式通常是HTML,也包括PDF、image及其他格式,用户用URI来指定所请求资源的位置。
[2]浏览器的结构
[用户接口 user interface]包括地址栏、书签选项、前进后退、刷新、暂停、主页等窗口上除了网页显示区域以外的部分
[浏览器引擎 browser engine]查询与操作渲染引擎的接口
[渲染引擎 rendering engine]显示用CSS格式化的HTML与图片
[网络 network]用于网络请求,如HTTP请求,它包括平台无关的接口和各平台独立的实现
[UI后端 UI backend]绘制基础元件,如组合框与窗口,提供平台无关的接口,内部使用操作系统的相应实现
[JS解释器 javascript interpreter]用于解析执行Javascript代码
[数据存储 data persistence]浏览器需要把所有数据存到硬盘上,如cookies
[3]渲染引擎
firefox使用的是geoko
safari和chrome使用的是webkit
[3.1]基本流程:渲染引擎首先通过网络获得所请求文档的内容,通常以8k分块的方式完成->解析html构建dom树->构造render树->布局render树->绘制render树
[3.2]详细流程:渲染引擎开始解析html,并将标签转化为内容树中的dom节点。接着,解析外部css文件及style标签中的样式信息,这些样式信息以及html中的样式信息将被用来构建另一棵树-render树。render树由一些包含css属性的矩形组成,它们将被按照正确的顺序显示到屏幕上。render树构建好之后,将会执行布局过程,它将确定每个节点在屏幕上的确切坐标。再下一步就是绘制,即遍历render树,并使用UI后端层绘制每个节点。
[3.3]特点:为了更好的用户体验,渲染引擎将会尽可能早的将内容呈现到屏幕上,并不会等到所有的html都解析完成之后再去构建和布局render树,它是解析完一部分内容就显示一部分内容,同时,可能还在通过网络下载其余内容。
[3.4]注意:webkit中元素的定位称为布局,而gecko中称为回流。
[4]解析与DOM树构建(parsing and DOM tree construction)
[4.1]html解析
[4.1.1]html不能被一般的自顶向下或者自底向上的解析器所解析的原因如下:
[1]这门语言本身的宽容特性
[2]浏览器对一些常见的非法html有容错机制
[3]解析过程是往复的,通常源码不会有解析过程中发生改变,但在html中,脚本标签包含document.write可能添加标签,这说明在解析过程中实际上修改了输入
[4.1.2]html5规范中描述了html的解析算法:包括两个阶段——符号化及构建树。符号化是词法分析的过程,将输入解析为符号,html的符号包括开始标签、结束标签、属性名及属性值,符号识别器识别出符号后,将其传递给树构建器,并读取下一个字符,以识别下一个符号,这样直到处理完所有输入。
[4.2]css解析
[4.2.1]特性:css解析属于上下文无关文法
[4.2.2]实现:webkit使用flex和bison解析生成器从css语法文件中自动生成解析器。Bison创建一个自底向上的解析器,firefox使用自顶向下解析器。它们都将每个css文件解析为样式表对象,每个对象包含css规则,css规则对象包含选择器和声明对象,以及其他一些符合css语法的对象。
[4.2.3] 处理脚本及样式表的顺序
[4.2.3.1]脚本:web的模式是同步的。开发者可以将脚本标识为defer,以使其不阻塞文档解析,并在文档解析结束后执行。
[4.2.3.2]预解析:当执行脚本时,另一个线程解析剩下的文档,并加载后面需要通过网络加载的资源。这种方式可以使资源并行加载从而使整体速度更快。
[4.2.3.3]样式表:脚本可能在文档的解析过程中请求样式信息,如果样式还没有加载和解析,脚本将得到错误的值,firefox在存在样式表还在加载和解析时阻塞所有的脚本,而chrome只在当脚本试图访问某些可能被未加载的样式表所影响的特定的样式属性时才阻塞这些脚本。
[5]渲染树构建
[5.1]当DOM树构建完成时,浏览器开始构建另一棵树——渲染树,渲染树由元素显示序列中的可见元素组成,它是文档的可视化表示,构建这棵树是为了以正确的顺序绘制文档内容。
[5.2]实现:firefox将渲染树中的元素称为frames,webkit则用renderer或渲染对象来描述这些元素。
[5.3]渲染对象和DOM元素相对应,但这种对应关系不是一对一的,不可见的DOM元素不会被插入渲染树,例如head元素另外display属性为none的元素也不会出现在渲染树中,而visibility属性为hidden的元素将出现在渲染树中
[5.4]创建树的流程:
[5.4.1]firefox中,表述为一个监听DOM更新的监听器,将frame的创建委派给frame constructor,这个构建器计算样式,并创建一个frame
[5.4.2]webkit中计算样式生成渲染对象的过程称为attachment,每个dom节点有一个attach方法,attachment的过程是同步的,调用新节点的attach方法将节点插入到dom树中
[6]布局
[6.1]当渲染对象被创建并添加到树中,它们并没有位置和大小,计算这些值的过程称为layout或reflow
[6.2]全局和增量layout
[6.2.1]当layout在整棵渲染树触发时,称为全局layout,这可能在下面这些情况下发生:
1、一个全局的样式改变影响所有的渲染对象,比如字号的改变
2、窗口resize
全局layout一般是同步触发,有些时候,layout会被当作一个初始layout之后的回调,比如滑动条的滑动。
[6.2.2]增量layout的过程是异步的,firefox为增量layout生成了reflow队列,以及一个调度执行这些批处理命令。webkit也有一个计时器用来执行增量layout——遍历树,为dirty状态的渲染对象重新布局。当脚本请求样式信息时,例如offsetHeight,会同步触发增量布局。
[6.3]当一个渲染对象在布局过程中需要折行时,则暂停并告诉它的parent需要折行,parent将创建额外的渲染对象并调用它们的layout
[7]绘制 painting
[7.1]绘制阶段,遍历渲染树并调用渲染对象的paint方法将它们的内容显示在屏幕上,绘制使用UI基础组件
[7.2]一个块渲染对象的堆栈顺序是:背景色->背景图->border->children->outline
[7.3]动态变化:浏览器总是试着以最小的动作响应一个变化,所以一个元素颜色的变化将只导致该元素的重绘,元素位置的变化将大致元素的布局和重绘,添加一个DOM节点,也会导致这个元素的布局和重绘。一些主要的变化,比如增加html元素的字号,将会导致缓存失效,从而引起整体的布局和重绘。
浏览器的工作原理