http://www.html5rocks.com/en/tutorials/internals/howbrowserswork/
主要结构
1、用户界面 如:地址栏,前进后退按钮,书签等
2、浏览器引擎 在用户界面和渲染引擎之间传输指令
3、呈现引擎 解析显示用户请求的内容,几乎都是单线程 除了网络操作
(ie->Trident; firefox->Gecko; Safair->Webkit; chrome and opera ->Blink)
4、网络 应对网络请求,例如http请求
5、用户界面后端 用来绘画基础的窗口部件
6、javascript编译器
7、数据存储 在本地储存各种数据
首先渲染引擎把html解析成DOM树(内容树),每个标签都是一个节点,根节点就是 document ,DOM树包含了所有的html标签,包括display:none的,或者是javascript 加载的元素,然后渲染引擎会解析样式(包括内部和外部的),去掉浏览器不能识别的样式,把样式信息和html中可见的结构结合起来用于创建呈现树(render tree)
webkit呈现引擎的主流程
gecko的主流程
render tree 类似于DOM ,但是区别很大,render tree 能识别样式,里面的每个节点都有自己的样式,渲染树不包括非可视化元素(例如 display:none 的元素和 head 标签),呈现树上元素为带有可视属性(颜色、尺寸等)的矩形组成,它们按照正确的顺序排列。render tree构建完成后,就进入布局流程,给呈现树上每个节点赋予在屏幕上显示时的准确坐标,然后就是painting,遍历呈现树然后用每个节点都会被 UI backend 画上屏幕。这是一个渐进的过程,为了更好的体验,渲染引擎不必等到整个html加载完毕,就会开始构建呈现树和设置布局,在不断接收剩余内容的同时,渲染引擎就会将部分内容解析显示出来
render tree和DOM树的关系
about parser
解析一个文档就是把它翻译成一种有意义代码能理解的结构,结果通常是把文档的结构翻译成由节点组成的树形结构,称之为一个解析树(a parse tree),解析基于文档遵循的语法规则。能够解析的格式称之为 context free grammar(上下文无关语言) ,由特定词汇和语法规则组成,不是人类使用的语言。因此解析时分两个组件 词汇分析 和 语法分析。
有两种解析程序,自上而下和自下而上,自上而下的从最高的规则开始解析,而自下而上的会扫描进来内容直到有规则匹配
HTML parse
HTML不能被上面说的解析程序解析,因为它不是 context free grammar,HTML语法宽松不严谨,它不能被 XML 解析程序解析,它的定义标准是一种 DTD 格式。
HTML有自己的解析程序,分为 tokenization 和 tree construction ,当tree construction解析完成后,该文档被标记为可交互的,然后处理 deferred 脚本,然后 才会触发 load 事件
DOM
DOM 是文档对象模型的缩写,是HTML文档的对象表示,同时也是外部内容(如javascript)与HTML 元素之间交互的接口,DOM 和HTML 标签几乎是一一对应关系
CSS parsing
css是 context free grammar , 把每个CSS 文件解析成StyleSheet Object,每个对象包含CSS rules
Javascript 和 CSS 处理顺序
web 模型是同步的,当解析程序遇到<script>会立刻解析和执行其中代码,中断对文档的解析直到脚本被执行完,如果脚本式外部导入的,那么必须中断解析从网络中取得外部脚本。如果不想中断解析可以给脚本添加 defer属性,在html5 可以把脚本标记为 asynchronous (异步的)
webkit 和 firefox 对此作了优化,当解析运行脚本的时候,其他线程继续解析,但要注意的是,它只是解析加载外部的资源,像外部导入的 CSS , Javascript , 图片, 它并不会对DOM进行修改,这由主线程负责。
CSS 就不一样,它不会中断文档的解析,除非脚本中断时需要用到,如果此时该 CSS 还没有没加载或者解析,会导致脚本执行出不正确的结果,所以firefox 会禁止所有脚本当CSS还没有被加载和解析完,webkit 会禁止脚本当它需要操作的样式属性可能被未加载的 CSS 影响时。
JS引擎大致执行步骤:
1. JS引擎会先预编译一次,预编译就是创建当前执行环境下的活动对象(当前作用域,可用变量的集合),将当前环境下var申明的变量先初始化为undefined,而function保留字定义的函数的字面量Literals会直接赋给活动对象。
2. JS引擎进入解析执行阶段,从上到下逐行执行。遇到直接变量(1,2,"a")会直接处理;而遇到要解析的变量,会先从活动变量中查找,没有找到的话再从prototype,其次作用域链里查找。
在一个函数还未调用(apply,call,或"()")时,它在JS引擎中只是以字面量Literals的形式储存在对象中(就和字符串一样)
而当我们调用一个函数时,JS引擎又会在该函数内部按以上两步执行。