浏览器--渲染过程(二)

浏览器渲染原理(上)这篇文章讲述了,当我们在浏览器中输入一个url是如何得到响应数据的,这篇文章主要讲述,当获取到了响应页面的信息后,是如何将其渲染在屏幕上,呈现在用户眼前的。

在正式内容开始之前,先了解一下几个基本概念。

进程:一个进程就是一个程序的运行实例。启动一个程序的时候,操作系统会为该程序创建一块内存,用来存放代码,运行中的数据和一个执行任务的主线程,我们把这样的一个运行环境叫进程。

线程:线程是依附于进程的,而进程中使用多线程并行处理能提升运算效率。

线程与进程的几个特点

  1. 进程中的任意一线程执行出错,都会导致整个进程的崩溃。
  2. 线程之间共享进程中的数据。
  3. 当一个进程关闭之后,操作系统会回收进程所占用的内存。
  4. 进程之间的内容相互隔离。

现代浏览器一般都是多进程的,包括浏览器进程,GPU进程,网络进程,渲染进程,插件进程等多个。

浏览器进程。主要负责界面显示、用户交互、子进程管理,同时提供存储等功能

渲染进程。核心任务是将 HTML、CSS 和 JavaScript 转换为用户可以与之交互的网页,排版引擎 Blink 和 JavaScript 引擎 V8 都是运行在该进程中,默认情况下,Chrome 会为每个 Tab 标签创建一个渲染进程。出于安全考虑,渲染进程都是运行在沙箱模式下

GPU 进程。其实,Chrome 刚开始发布的时候是没有 GPU 进程的。而 GPU 的使用初衷是为了实现 3D CSS 的效果,只是随后网页、Chrome 的 UI 界面都选择采用 GPU 来绘制,这使得 GPU 成为浏览器普遍的需求。最后,Chrome 在其多进程架构上也引入了 GPU 进程

网络进程。主要负责页面的网络资源加载,之前是作为一个模块运行在浏览器进程里面的,直至最近才独立出来,成为一个单独的进程

插件进程。主要是负责插件的运行,因插件易崩溃,所以需要通过插件进程来隔离,以保证插件进程崩溃不会对浏览器和页面造成影响

所以,当我们打开进程的时候,仅仅打开了一个页面,却可能有多个进程,因为打开了一个页面至少有一个网络进程,一个浏览器进程,一个GPU进程,以及一个渲染进程,还有可能加上插件进程。

我们从服务器获取的html,css,JavaScript他们是如何构建成一个完整的页面的呢?

1、构建DOM树

浏览器是不能直接理解和使用html的,需要将 HTML 转换为浏览器能够理解的结构——DOM 树。也就是说,html需要经过html解析器,最终输出树状结构的 DOM。

浏览器首先将html的原始字节数据转换为文件指定编码的字符,这种转换是基于html文件的字符编码完成的,字符会被进一步解析为‘标记(token)’,也有人叫令牌,token记录了标签的开始与结束,通过这个特性可以轻松判断一个标签是否为子标签等。解析为标记(token)后,会将每个token转换成定义其属性和规则的节点对象,这些节点对象就是将被链接到称为DOM的数据结构中,DOM简历起了父子关系,相邻兄弟关系等,在这个 DOM 对象中,每个节点之间都建立了关系,也就是树状结构的 DOM。

整个DOM树的构建过程其实就是:

字节 -> 字符 -> 标记(token) -> 节点对象 -> 对象模型

DOM 和 HTML 内容几乎是一样的,但是和 HTML 不同的是,DOM 是保存在内存中树状结构,可以通过 JavaScript 来查询或修改其内容。

<html>
  <head>
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <link href="style.css" rel="stylesheet">
    <title>Critical Path</title>
  </head>
  <body>
    <p>Hello <span>web performance</span> students!</p>
    <div><img src="awesome-photo.jpg"></div>
  </body>
</html>

2、构建CSSOM和样式计算

css样式的主要来源有是那种,link引入外部css文件,style标签的css,元素的style属性内嵌的css。

当HTML代码遇见标签时,浏览器会发送请求获得该标签中标记的CSS文件(使用内联CSS可以省略请求的步骤提高速度,但没有必要为了这点速度而丢失了模块化与可维护性),

和 HTML 文件一样,浏览器也是无法直接理解这些纯文本的 CSS 样式,所以当浏览器接收到 CSS 的原始字节时,会启动一个和处理 HTML 原始字节类似的过程。就是说,原始数据字节被转换成字符,然后标记,然后形成节点,节点形成css的树结构,称为css对象模型,也叫CSSOM。
CSSOM定义了一些API,web开发者使用这些API就可以进行检查,更改文档及文档视觉属性,包括布局定位,视图宽度等。

比如当我们在控制台输入document.styleSheets

这个样式表包含了很多种样式,已经把那三种来源的样式都包含进去了。渲染引擎会把获取到的 CSS 文本全部转换为 styleSheets 结构中的数据,并且该结构同时具备了查询和修改功能。

image.png

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

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

2em 被解析成了 32px,red 被解析成了 rgb(255,0,0),bold 被解析成了 700……

样式的属性已被标准化了,接下来就需要计算 DOM 树中每个节点的样式属性。

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

每个节点的具体样式,需要综合三种css来源对标签的描述,利用css继承、css优先级、css层叠规则等计算出来,我们可以在chrome浏览器的Element标签中看到

image.png

这里划线的表示没有采用的样式,如果想看到一个标签最终应用的全部样式,可以在Chrome浏览器的Element标签下,选中摸个标签,点击computed,即可看到应用在这个标签下的所有格式化好的样式。


image.png

3、构建渲染树

DOM树描述了文档的结构与内容,CSSOM描述了对文档应用的样式规则,浏览器拥有了这两个对象集合之后最终会将两者结合在一起,形成渲染树。

浏览器会先从DOM树的根节点开始遍历每个可见节点,并把这些节点添加到渲染树中。

不可见的节点不会渲染到页面上,比如CSS设置了display: none属性的节点,值得注意的是visibility: hidden属性并不算是不可见属性,它的语义是隐藏元素,但元素仍然占据着布局空间,所以它会被渲染成一个空框

对每个可见节点,找到其适配的CSS样式规则并应用。 - 渲染树构建完成,每个节点都是可见节点并且都含有其内容和对应规则的样式。

渲染树

3、布局阶段

当浏览器生成渲染树以后,就会根据渲染树来进行布局(也可以叫做回流)。这一阶段浏览器要做的事情是要弄清楚各个节点在页面中的确切位置和大小。通常这一行为也被称为“自动重排”。

这时候css盒模型就闪亮登场了,CSS采用了一种叫做盒子模型的思维模型来表示每个节点与其他元素之间的距离,盒子模型包括外边距(Margin),内边距(Padding),边框(Border),内容(Content)。页面中的每个标签其实都是一个个盒子

css盒模型

布局阶段会从渲染树的根节点开始遍历,然后确定每个节点对象在页面上的确切大小与位置,布局阶段的输出是一个盒子模型,它会精确地捕获每个元素在屏幕内的确切位置与大小,所有相对的测量值也都会被转换为屏幕内的绝对像素值。

现在我们有了布局树,也知道了每个标签的位置信息,就会进行下一步,分层

4、分层阶段

其实浏览器的页面实际上被分成了许多层,这些图层叠加后才形成了最终的页面。

比如一些复杂的css动画,z-index等,渲染引擎会为他们生成专用的图层,并生成对应的图层树。在chrome的Layers下 可以可视化页面的分层情况,以B站为例,如图所示:

image.png

通常情况,并不是布局树的每一个节点都包含一个图层,如果节点没有对应的图层,那么这个节点就从属于父节点的图层,也就是说,每个节点都会直接或间接的从属于某一个图层。

如何提升单独的图层?

1、拥有层叠上下文属性

比如,明确定位的元素,定义透明的元素,使用css滤镜的元素等等,具体可参考层叠上下文

image.png

2、需要被裁剪的地方也会被创建单独的图层

比如说一个200*200的div元素,如果文字内容过多,超出了元素面积,就会产生裁剪,渲染引擎会把裁剪的一部分内容用于现在在div中,出现这种情况的时候,渲染引擎会为文字部分单独创建一个层,如果出现滚动条,滚动条也会被提升为单独的层。


image.png

5、图层绘制、分块、光栅化和合成

构建完图层之后,渲染引擎会对图层树中的每个元素进行绘制,首先,会把一个图层的绘制拆分成很多小的指令,再把这些指令按照顺序组成一个待绘制列表,并将其提交给合成线程,合成线程将图层分成图块(因为一个页面可能很大,而用户只能看到视口中页面的一部分,如果全部绘制开销会很大,所以合成线程会按照视口附近的图块来优先生成位图,实际生成位图的操作是由栅格化来执行的。所谓栅格化,是指将图块转换为位图),并在光栅化线程池中将图块转换成位图,然后发送绘制图块命令给浏览器进程,浏览器进程根据 绘制图块命令生成页面,并显示到显示器上。

一个完整的渲染流程图大致如下

image.png

了解了浏览器渲染的整个流程,有助于我们回顾工作中没有注意的知识点,以及如何优化页面的渲染。

css优先级

上文说到构建CSSOM的时候会计算每个节点的具体样式,从而引出css优先级。

1、important 表示强制应用该样式,用来覆盖内联样式和权重比较高的选择器的样式
2、如果比较后权重相同,那么后者覆盖前者,后渲染的胜出;
3、内联样式 > id选择器样式 > 类选择器样式 > 元素选择器样式;

css硬件加速

所谓硬件加速就是将浏览器的渲染过程交给GPU处理,而不是使用浏览器的渲染引擎。这样就可以使得animation与transition更加顺畅,但是CSS animations, transforms 以及 transitions 不会自动开启GPU加速,我们可以对元素使用一些css规则去触发硬件加速,比如transform: translateZ(0)

.cube {
   -webkit-transform: translateZ(0);
   -moz-transform: translateZ(0);
   -ms-transform: translateZ(0);
   -o-transform: translateZ(0);
   transform: translateZ(0);
   /* Other transform properties here */
}

在 Chrome and Safari中,当我们使用CSS transforms 或者 animations时可能会有页面闪烁的效果,下面的代码可以修复此情况:

.cube {
   -webkit-backface-visibility: hidden;
   -moz-backface-visibility: hidden;
   -ms-backface-visibility: hidden;
   backface-visibility: hidden;
 
   -webkit-perspective: 1000;
   -moz-perspective: 1000;
   -ms-perspective: 1000;
   perspective: 1000;
   /* Other transform properties here */
}

在webkit内核的浏览器中,另一个行之有效的方法是

.cube {
   -webkit-transform: translate3d(0, 0, 0);
   -moz-transform: translate3d(0, 0, 0);
   -ms-transform: translate3d(0, 0, 0);
   transform: translate3d(0, 0, 0);
  /* Other transform properties here */
}

不过使用GPU可能会导致严重的性能问题,因为它增加了内存的使用,而且它会减少移动端设备的电池寿命。

css盒模型
在布局阶段,为了定位每个元素在页面具体大小与位置,引出了css盒模型。

image.png

标准盒模型下盒子的大小 = content + border + padding + margin

怪异盒模型下盒子的大小=width(content + border + padding) + margin

可以用box-sizing来设置盒子模型的解析模式
content-box: 默认值,border和padding不算到width范围内,可以理解为是W3c的标准模型(default)
border-box:border和padding划归到width范围内,可以理解为是IE的怪异盒模型
padding-box:将padding算入width范围

同时根据盒模型还能引出,块级上下文(BFC),上下margin重合等各种布局问题,可以百度css面试题会有很多专门整理的css面试题,例如CSS经典面试题(史上最全,持续更新中...)

重绘和重排

更新元素的几何属性:重排

重排

当Render Tree中部分或全部元素的尺寸,结构,或某些属性发生改变时,浏览器重新渲染部分或全部文档的过程称为重排

如果你通过 JavaScript 或者 CSS 修改元素的几何位置属性,例如改变元素的宽度、高度等,那么浏览器会触发重新布局,解析之后的一系列子阶段,这个过程就叫重排。无疑,重排需要更新完整的渲染流水线,所以开销也是最大的。

会导致重排的操作:
1、页面首次渲染
2、添加或删除课件的DOM元素
3、元素位置改变
4、元素内容改变(例如:一个文本被另一个不同尺寸的图片替代)
5、浏览器窗口尺寸改变

更新元素的绘制属性:重绘

重绘

当页面中的元素样式的改变并不影响它在文档流中的位置时候,(例如:color、background-color、visibility等),浏览器会将新样式赋予给元素并重新绘制它,这个过程称为重绘

相较于重排操作,重绘省去了布局和分层阶段,所以执行效率会比重排操作要高一些。

针对css:
1.避免使用table布局
2.尽可能在DOM树的最末端改变class
3.避免设置多层内联样式
4.将动画效果应用到position属性为absolute或fixed的元素上
5.避免使用css表达式(calc())

所以当实现动画的时候,使用css3属性比使用定位更能优化性能


image.png

transform 实现动画效果,可以避开重排和重绘阶段,直接在非主线程上执行合成动画操作,相对于重绘和重排,合成能大大提升绘制效率。

本文参考:

浏览器工作原理与实践

浏览器页面渲染机制 ,了解一下?

浏览器渲染机制

CSSOM中文资料

用CSS开启硬件加速来提高网站性能

css盒模型理解

css盒子模型与怪异模型

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