chrome浏览器在地址栏输入URL到页面展示,这中间发生了什么?(中)

距上次的导航流程已有些日子,趁着这次休假把剩下的渲染流程也分享出来。
通过本文可以透视浏览器是如何进行渲染工作的。

众所周知,浏览器传输的相关文件包括 js文件html文件css文件。

//HTMl: 超文本 标记语言
<p>山野乔治</p>
//CSS:层叠样式表 
p { color: red }
//JavaScript
p.style.color = 'gray'  通过页面修改内容

1.html的内容由标记和文本组成,标记也称为标签。每个标签都有自己特定的含义,浏览器会根据不同的语义化的标签来进行渲染不同的内容。比如上面的的<p>标签会告诉浏览器在这里需要创建一个新的段落,中间的文本就是段落要显示的内容。

2.css文件又称为层叠样式表,是由选择器和属性组成。通过css可以改变文字的大小,颜色等信息。图中的p标签,会把设定的属性值,全部应用到p标签上。

3.至于JavaScript,使用这个可以让页面的内容‘动’起来。也就是大部分的用户和浏览器的交互操作,都是通过JavaScript完成的。


搞清楚了HTML,CSS,JavaScript基本含义之后,我们就开始详细了解浏览器的渲染机制吧。

渲染模块在执行过程中会被划分为很多子阶段,输入的HTML经过这些子阶段,最后输出为了像素。我们把这样的一个处理流程就叫做渲染流水线,大致过程如下图所示。

img

按照渲染的时间顺序,流水线可以分为这几个子阶段:

  • 构建DOM树
  • 样式计算
  • 布局阶段
  • 分层
  • 绘制
  • 分块
  • 光栅化
  • 合成

每个阶段的过程中,我们应该重点关注:1,开始每个子阶段都有其输入的内容;2,然后每个子阶段有其处理过程;3,最终子阶段会生成其输出内容。也就是:输入-》加工-》输出

构建DOM树

为什么要构建DOM树呢?

我们浏览器是无法直接理解和使用HTML的(HTML标记语言是为了让开发人员进行编程的语言)所以浏览器需要将转化为浏览器可以理解的结构,那就是---DOM树。

了解过数据结构的开发人员应该都清楚什么是树结构。有一父节点可以有很多个子节点,但一个子节点不能被不同的父节点共享。在我们浏览器的渲染机制中,就频繁的使用到了树结构。

那么DOM树是如何进行构建并进行渲染的呢?

DOM树构建过程.png

在构建DOM树的时候,输入内容就是一个简单的HTML文件,然后由HTML解析器进行解析,最终输出一个树状结构的DOM。

为了能直观的了解什么是DOM结构,可以在控制台上输入document进行查看完整的一个DOM结构。DOM和HTML内容几乎一摸一样的,但是和HTML不同的是,DOM是保存在内存中的树状结构,可以通过JavaScript来查询或修改其内容。如何通过JavaScript来修改DOM的内容呢?控制台输入以下内容

document.getElementsByTagName('p')[0].innerText = 'black'

这个代码作用就是把第一个P标签的文本内容转换为black。当执行这行代码的时候,DOM的一个p节点的内容成功被修改,同时页面的内容也会被修改。

这就是生成DOM树的过程,此刻DOM节点的样式我们依然不知道,要让DOM拥有正确的样式,就需要进行下一个渲染子进程了。

样式计算(Recalculate Style)

样式计算的目的是为了计算DOM节点中每个元素的具体样式,这个子进程大概需要分为三步来完成。

1.把CSS转化为浏览器能够理解的结构

那么CSS样式的来源主要有哪些呢?

  • 通过link引用的外部CSS文件

  • <style>标记内的CSS

  • 元素的style属性内嵌的CSS

和第一个构建DOM树一样,浏览器也是不能直接理解纯文本的CSS样式,所以当渲染引擎就收到css文件的时候,首先会进行一个转化操作,将css文本转化为浏览器可以理解的结构---styleSheets

同样,想要更要直观的查看styleSheets的结构,我们可以在控制台输入document.styleSheets,就能看到对应的css结构。

styleSheets.png

可以看出,这个样式表包含了很多样式,已经把那三种来源的样式都包含进去了。当然样式表的具体结构在这里不赘述,只介绍渲染引擎会把获取到的CSS文件全部转换为styleSheets结构中的数据,并且该结构同时具备了查询和修改功能,为后面的样式操作提供了基础。到此样式表转化完毕。

2.转换样式表中的属性值,使其标准化

我们已经把现有的CSS文本转化为了浏览器可以理解的结构了,那么接下来就要对其进行属性值的标准化操作。那么什么是属性值标准化呢?

body { font-size: 2em }
p { color: blue }
span { display: none }
div { font-weight: bold }
div p { color: green }
div { color: red }

可以看出上述的CSS文本中有很多的属性值,如2em,blue,bold。这些类型数值都不容易被渲染引擎所理解,所以需要将所有值转换为渲染引擎所能理解的标准化的计算值,这个过程就是属性值标准化。

那么标准化后的属性值是什么呢?

body { font-size: 32px }
p { color: rgb(0,0,255) }
span { display: none }
div { font-weight: 700 }
div p { color: rgb(0,128,0) }
div { color: rgb(255,0,0) )

3.计算出DOM树中的每个节点的具体样式

当属性值已经被标准化后,接下来我们就要计算DOM树中的每个节点的样式属性了,如何计算呢?

这就涉及到CSS的继承规则和层叠规则了。

首先是CSS继承。CSS继承就是每个DOM节点都包含有父节点的样式 这么说可能有点抽象,实例是如何应用的呢?

body { font-size: 20px }
p {color: blue}
span { display: none }
div { font-weight: bold; color: red }
div p { color: green }

那么如何继承呢?如下图所示

css继承.png

所有的子节点都继承了父节点的样式。比如body节点的font-size属性是20,那么body节点下面的所有节点的font-size都等于20。

样式计算过程中第二个规则就是样式层叠。层叠是CSS的一个基本特征,它是一个定义了如何合并来自多个源的属性值的算法。它在css中处于核心地位,css的全称是“层叠样式表”正是强调了这一点。关于层叠的具体规则这里不做介绍。

总之,样式计算阶段的目的救赎为了计算出DOM节点中每个元素的具体样式,在计算过程中需要遵守CSS的继承和层叠两个规则。这个阶段最中输出的内容就是每个DOM节点的样式,并被保存在ComputerStyle的结构内。

如果想要了解每个DOM元素最终的计算样式,可以打开Chrome的“开发者工具,选择一个element标签,然后再选择“Computer”子标签。

computer中存储最终计算的样式.png

在进行计算之后,我们就进行布局阶段。

布局阶段

我们有DOM树和DOM树中元素的样式之后,我们还不足以显示页面,因为还不知道DOM元素的几何位置信息。那么接下来就需要计算出DOM树中可见元素的几何位置,我们把这个计算过程叫做布局

Chrome在布局阶段需要完成两个任务:创建布局树和布局计算。

1.创建布局树

你可能注意到了DOM树还含有很多不可见的元素,比如head标签,还有使用了display:none属性的元素。所以在显示之前,我们还要额外地构建一棵只包含可见元素布局树。

我们结合下图来看看布局树的构造过程:

布局树构造过程.png

从上图可以看出,DOM树中所有不可见的节点都没有包含到布局树中。

为了构建布局树,浏览器大体上完成了下面这些工作:

  • 遍历DOM树中的所有可见节点,并把这些节点加到布局树中;
  • 而不可见的节点会被布局树忽略掉,如head标签下面的全部内容,再比如body.p.span这个元素,因为它的属性包含display:none,所以这个元素也没有被包进布局树。

2.布局计算

现在我们有了一棵完整的布局树。那么接下来,就要计算布局树节点的坐标位置了。布局的计算过程非常复杂,等到后续详解。

在执行布局操作的时候,会把布局计算的结果重新写会布局树中,所以布局树既是输入内容也是输出内容,这是布局阶段一个不合理的地方,因为在布局阶段并没有清晰地将输入内容和输出内容区分开。对于这个问题,Chrome团队正在重构布局代码,下一代布局系统叫做LayoutNG,试图分离输入和输出,从而让布局算法更加简单。

综上本问介绍了渲染进程的三个子进程:DOM生成,样式计算和布局。

总结:

  • 浏览器不能直接理解HTML文件,通过转化器将转化为浏览器能理解的DOM树结构。
  • 生成DOM树之后,还需要根据CSS样式表,来计算出DOM树所有节点的样式。
  • 最后计算DOM元素的布局信息,使其保存在布局树中(输入DOM树,计算布局信息后,输出DOM树)。

子过程比较多,小伙伴迫切叫我健身。渲染进程那就先到这里了,剩下的进程我们下节再叙~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,588评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,456评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,146评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,387评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,481评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,510评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,522评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,296评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,745评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,039评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,202评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,901评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,538评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,165评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,415评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,081评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,085评论 2 352