浏览器(三)渲染进程(浏览器内核)

一、概述


渲染进程与我们前端日常开发生活息息相关,需要着重了解。可以这样理解,页面的渲染,JS的执行,事件的循环,都在这个进程内进行。

二、渲染进程包含哪些线程呢?

  1. GUI渲染线程
    • 当浏览器收到响应的html后,该线程开始解析HTML文档构建DOM树,解析CSS文件构建CSSOM,合并构成渲染树,并计算布局样式,绘制在页面上(该处可深挖的坑,HTML解析规则,CSS解析规则,渲染流程细节)
    • 当界面样式被修改的时候可能会触发reflow和repaint,该线程就会重新计算,重新绘制,是前端开发需要着重优化的点

  2. JS引擎线程
    • JS内核,也称JS引擎(例如V8引擎),负责处理执行javascript脚本程序,
    • 由于js是单线程(一个Tab页内中无论什么时候都只有一个JS线程在运行JS程序),依靠任务队列来进行js代码的执行,所以js引擎会一直等待着任务队列中任务的到来,然后加以处理。

  3. 事件触发线程
    • 归属于渲染(浏览器内核)进程,不受JS引擎线程控制。主要用于控制事件(例如鼠标,键盘等事件),当该事件被触发时候,事件触发线程就会把该事件的处理函数添加进任务队列中,等待JS引擎线程空闲后执行

  4. 定时器出发线程
    • 传说中的setInterval与setTimeout所在线程
    • 浏览器的定时器并不是由JavaScript引擎计数的,因为JavaScript引擎是单线程的, 如果处于阻塞线程状态就会影响计时的准确,因此通过单独的线程来计时并触发定时器,计时完毕后,满足定时器的触发条件,则将定时器的处理函数添加进任务队列中,等待JS引擎线程空闲后执行。
    • W3C在HTML标准中规定,规定要求setTimeout中低于4ms的时间间隔算为4ms

  5. 异步HTTP请求线程
    • 当XMLHttpRequest连接后,浏览器会新开的一个线程,当监控到readyState状态变更时,如果设置了该状态的回调函数,则将该状态的处理函数推进任务队列中,等待JS引擎线程空闲后执行
      注意:浏览器对通一域名请求的并发连接数是有限制的,Chrome和Firefox限制数为6个,ie8则为10个。

总结:2-5 四个线程参与了JS的执行,但是永远只有JS引擎线程在执行JS脚本程序,其他三个线程只负责将满足触发条件的处理函数推进任务队列,等待JS引擎线程执行。
在这里插入图片描述


三、GUI渲染线程与JS引擎线程互斥


由于JavaScript是可操纵DOM的,如果在修改这些元素属性同时渲染界面(即JS线程和UI线程同时运行),那么渲染线程前后获得的元素数据就可能不一致了。

因此为了防止渲染出现不可预期的结果,浏览器设置GUI渲染线程与JS引擎为互斥的关系。

当JS引擎执行时GUI线程会被挂起,GUI更新则会被保存在一个队列中等到JS引擎线程空闲时立即被执行。


四、JS阻塞页面加载


从上述的互斥关系,可以推导出,JS如果执行时间过长就会阻塞页面。

譬如,假设JS引擎正在进行巨量的计算,此时就算GUI有更新,也会被保存到队列中,等待JS引擎空闲后执行。然后,由于巨量计算,所以JS引擎很可能很久很久后才能空闲,自然会感觉到巨卡无比。

所以,要尽量避免JS执行时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞的感觉。


五、CSS加载是否会阻塞DOM树渲染?


  • css加载不会阻塞DOM树解析(css是由单独的下载线程异步下载的。异步加载时DOM照常构建)
  • 但会阻塞render树渲染(渲染时需等css加载完毕,因为render树需要css信息)

为什么会阻塞render树的渲染?

这可能也是浏览器的一种优化机制。

因为你加载css的时候,可能会修改下面DOM节点的样式,如果css加载不阻塞render树渲染的话,那么当css加载完之后,render树可能又得重新重绘或者回流了,这就造成了一些没有必要的损耗。

所以干脆就先把DOM树的结构先解析完,把可以做的工作做完,然后等你css加载完之后,在根据最终的样式来渲染render树,这种做法性能方面确实会比较好一点。


六、浏览器的渲染过程

  • 概念
    • DOM Tree: 浏览器将HTML解析成树形的数据结构。
    • CSS Rule Tree:浏览器将CSS解析成树形的数据结构。
    • Render TreeDOM树和CSS规则树合并后生产Render树。
    • Layout(布局):有了Render Tree,浏览器已经能知道网页中有哪些节点、各个节点的CSS定义以及他们的从属关系,从而去计算出每个节点在屏幕中的位置。
    • Painting(绘制): 按照算出来的规则,通过显卡,把内容画到屏幕上。
    • Reflow(回流):当浏览器发现某个部分发生了点变化影响了布局,需要倒回去重新渲染,内行称这个回退的过程叫 reflow
    • Repaint(重绘):改变某个元素的背景色、文字颜色、边框颜色等等不影响它周围或内部布局的属性时,屏幕的一部分要重画,但是元素的几何尺寸没有变。
    • 注意:display:none的节点不会被加入Render Tree,而visibility: hidden则会,所以display:none会触发reflowvisibility: hidden会触发repaint

  • 浏览器内核(渲染进程)拿到响应报文之后,渲染大概分为以下步骤:
    1. 解析HTML生成DOM Tree,同时浏览器主进程负责下载CSS文件
    2. CSS文件下载完成,解析CSS生成CSS Tree
    3. 根据DOM TreeCSS Tree生成Render Tree
    4. 根据Render树进行Layout,负责各个元素节点的尺寸、位置计算。
    5. 绘制Render树(Painting),绘制页面像素信息。
    6. 浏览器主进程将默认图层复合图层交给GPU进程,GPU进程再将各个图层合成(composite),最后显示出页面

  • 渲染完毕后JS引擎开始执行load事件,绘制流程见下图:
    在这里插入图片描述

  • load事件与DOMContentLoaded事件的先后

    • DOMContentLoaded事件触发时,仅当DOM加载完成,不包括样式表,图片。(譬如如果有async加载的脚本就不一定完成)

    • onload事件触发时,页面上所有的DOM,样式表,脚本,图片都已经加载完成了。(渲染完毕了)
      所以,顺序是:DOMContentLoaded -> load


七、普通图层和复合图层

渲染步骤中就提到了composite概念。

可以简单的这样理解,浏览器渲染的图层一般包含两大类:普通图层以及复合图层

首先,普通文档流内可以理解为一个复合图层(这里称为默认复合层,里面不管添加多少元素,其实都是在同一个复合图层中)

其次,absolute布局(fixed也一样),虽然可以脱离普通文档流,但它仍然属于默认复合层。

然后,可以通过硬件加速的方式,声明一个新的复合图层,它会单独分配资源
(当然也会脱离普通文档流,这样一来,不管这个复合图层中怎么变化,也不会影响默认复合层里的回流重绘)

可以简单理解下:GPU中,各个复合图层是单独绘制的,所以互不影响,这也是为什么某些场景硬件加速效果一级棒

可以Chrome源码调试 -> More Tools -> Rendering -> Layer borders 中看到,黄色的就是复合图层信息


  • 复合图层的好处
    • 合成层的位图,会交由 GPU 合成,比 CPU 处理要快
    • 当需要 repaint 时,只需要 repaint 本身,不会影响到其他的层
    • 对于 transformopacity 效果,不会触发 layoutpaint
    • 但是尽量不要大量使用复合图层,否则由于资源消耗过度,页面反而会变的更卡

  • 如何变成复合图层(硬件加速)
    • 最常用的方式:translate3dtranslateZ3D或透视变换)
    • <video><iframe><canvas><webgl>等元素
    • 元素有一个 z-index 较低且包含一个复合层的兄弟元素(换句话说就是该元素在复合层上面渲染)
    • 元素有一个包含复合层的后代节点(换句话说,就是一个元素拥有一个子元素,该子元素在自己的层里)

  • 硬件加速时请使用index
    • 使用3D硬件加速提升动画性能时,最好给元素增加一个z-index属性,人为干扰合成层的排序,可以有效减少chrome创建不必要的合成层,防止层爆炸,提升渲染性能,移动端优化效果尤为明显。
    • 原理:如果这个元素添加了硬件加速,并且index层级比较低,那么在这个元素的后面其它元素(层级比这个元素高的,或者相同的,并且releativeabsolute属性相同的), 会默认变为复合层渲染,如果处理不当会极大的影响性能
    • 简单理解:如果a是一个复合图层,而且b在a上面,那么b也会被隐式转为一个复合图层
    • 问题验证:http://web.jobbole.com/83575/

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值