浏览器的渲染

首先当网络线程拿到html文档的时候会生成一个渲染任务交给渲染主线程的消息队列,在事件循环的机制下;渲染主线程会取出消息队列的渲染任务开始渲染流程
渲染流程会经历以下步骤

解析HTML
样式计算
布局
分层
绘制
分块
光栅化
像素

在浏览器解析html的过程中
浏览器会额外启动一个预解析线程来处理文档中的link标签或者说外部的js(这里指得是 <script src="xxx"></script>这里的src引用的是外部资源)以及其他的外部资源(网络图片等);这个预解析线程会提前下载(这里的下载是通知网络线程去下载)这些文件,防止阻碍html的解析。

  • 首先是css资源的下载,一般预解析线程只承担下载不承担解析的工作,也有其他情况例如chrome的预解析线程会对css做一些优化处理(简单了解下就是去除空白字符注释,打标记等)这里的目的是为了让css解析器更快的构建CSSOM树

  • 这里我们还需要关注script标签引用外部资源的几种情况:
    <script src="xxx"></script> 这种情况虽然预解析线程会提前下载,但是当html解析到这行的时候会立即停止,等待下载完成,并执行完js代码才会继续html的解析工作
    <script src="xxx" defer></script> 下载和解析并行,这个不会阻塞html的解析,下载完成后也会等待整个文档解析完毕,再按文档中的出现顺序依次执行内部js
    <script src="xxx" async></script> 下载和解析并行,但是下载完成后会立即停止html的解析并执行内部js,当然这里的前提是需要html解析到这行,如果在html解析到这行之前就下载完成,会等待解析到这行才会执行内部js

html解析过程中会构建DOM树和CSSOM(css object model)树;

  • HTML会边解析边构建DOM树所以不会阻塞渲染;
  • 待所有css下载完成并且解析完成才会构建出完整的CSSOM树,所以构建CSSOM树会阻塞首次渲染

接下来到了样式计算
这里实际上就是给每个dom节点分配样式,这里我们了解下实际上不管咱们有没有对dom设置css属性,它们最终都有自己完整的css属性,如果没有设置会自动设置默认值,并且咱们设置css相对的值会计算成绝对值(比方说rem 会 转化为 px),这个过程的性能开销与DOM结构的复杂度(元素数量)和CSS选择器的复杂度直接相关

然后是布局(layout)
上面我们有提到DOM树,这里会通过DOM树和CSSOM树以及经过样式计算后来构建出渲染树,渲染树和DOM树是有差异的,渲染树只包含需要显示在屏幕上的节点(即 display: none 被排除在渲染树外);css视觉格式化模型规则:

  • 一个块容器盒,要么只包含块级盒子,要么建立一个行内格式化上下文(IFC)从而只包含行内级盒子(当违反上述规则时,浏览器会自动生成匿名盒子来修复)
  • 在这个匿名块级盒子内部,文本内容被进一步分解到匿名行盒中,而多行文本的每一行都会生成一个匿名行盒来包裹该行的所有行内内容。
//举例
<span>我是文字</span>
<div>我是文字</div>
//这里的span对应的dom树转为layout树只会额外生成一个匿名行盒作为span的子级来包裹内容
//这里的div 对应的dom树转为layout树的时候会受到CSS规范限制会生成一个匿名块盒作为div块盒的子级,这个匿名块盒会包含一个匿名行盒,匿名行盒中是内容

开发过小程序的小伙伴也知道有个text标签用来专门存放内容,但是可能直接用view标签了,看到这里咱们就明白使用view直接包含文本增加渲染树构建的复杂度。

接下来是分层,可以理解为浏览器会分为一层层去渲染,并不是一个平面,这里可能涉及到GPU加速,transform, opacity属性会影响分层结果,分层与GPU加速密切相关,独立的合成层是GPU加速的基础,通常使用will-change:transform 属性提示浏览器创建独立的合成层的方式来影响分层结果

绘制 和 分块 和 光栅化
这三个我们简单了解下,个人感觉不需要记浏览器是如何实现这块的(学习渲染的目的只是帮助我们去注意平时开发过程中有没有需要优化的点)
绘制:主线程会将每个层单独产生指令集;重绘是会从绘制这个步骤开始触发
分块:绘制步骤完成后,主线程将图层的绘制信息交给合成线程对图层进行分块;
光栅化:通过块获取绘制指令转换为位图的过程,通常在GPU进程中完成。合成则是将各个层按照正确顺序合并成最终图像。

画:渲染进程中的合成线程在完成分层和分块后,会将绘制信息传递给独立的GPU进程。GPU进程再通过电脑包硬件,将结果画到屏幕上。

关于reflow(重排) 就是由于布局发生了变化,浏览器需要从(或至少从)样式计算这一步开始,重新执行后续的整个渲染流水线,直到更新完布局树。
关于repaint(重绘)就是更改不需要重新计算布局,但需要更新元素的外观时,浏览器会跳过布局阶段,直接从绘制阶段开始执行后续的所有步骤
关于GPU加速:当元素的变换属性(如 transform, opacity)发生变化时,这时候会跳过布局、绘制、分层、分块、光栅化会直接到最后一步中画由合成线程处理再给GPU进程发送指令,所以说性能非常好

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值