浏览器渲染过程

浏览器渲染过程

浏览器采用流式布局模型(Flow Based Layout)

1. DOM 树:解析 HTML 构建DOM 树

当浏览器从服务器接收到HTML文档后,会开始从上到下解析HTML文档。在这个过程中,浏览器会将HTML标签转换为DOM(文档对象模型)节点,并构建出一个DOM树。这个DOM树是浏览器内部表示页面结构的一种方式,它包含了页面中的所有元素以及它们的属性和关系。

2. CSS 树:解析 CSS 构建 CSSOM树

同时,浏览器也会解析HTML中引用的CSS样式表。CSS样式表定义了页面中元素的样式和布局。浏览器会将这些样式信息解析为CSSOM(CSS对象模型)树。CSSOM树和DOM树是并行构建的,但它们的构建过程相互独立。

3. 渲染树:CSSOM 和 DOM 一起生成 Render Tree(渲染树)

一旦DOM树和CSSOM树都构建完成,浏览器会开始合并这两棵树,形成一个渲染树。渲染树只包含需要显示在屏幕上的节点和它们的样式信息。这个过程会排除掉那些对最终渲染结果没有影响的节点,比如display属性为none的元素。

4. 布局(layout):重排/回流

根据Render Tree浏览器就知道网页中有哪些节点,以及各个节点与 CSS 的关系,从而知道每个节点的位置和几何属性(重排),完成布局计算。
浏览器会采用流式处理的方法,只需要一次pass绘制操作就可以布局所有的元素。

5. 绘制(Paint):重绘

浏览器会根据渲染树和布局计算的结果,将每个节点绘制到屏幕上。这个过程称为绘制或渲染。(重绘)
绘制过程中,浏览器会考虑各种视觉效果,比如阴影、渐变等,以呈现出最终的页面效果。

过程如下图:
在这里插入图片描述

过程1、2、3非常快,但是4和5比较耗时

“重排” 和 “回流”是一个意思,指的是重新执行步骤4
“重绘” 指重新执行步骤5

浏览器的重绘与重排传送门

.

DOM 树 和 渲染树 的区别:

DOM 树与 HTML 标签一一对应,包括 head 和隐藏元素(display:none)
渲染树不包括 head 和隐藏元素(display:none),大段文本的每一个行都是独立节点,每一个节点都有对应的 css 属性


浏览器阻塞

自上而下解析HTML,逐渐构建起DOM tree,遇到style、link标签,会下载解析样式表,同时构建CSSOM tree,不会阻塞html的解析。但是遇到script标签,它会立即下载并执行得到的脚本,会阻塞HTML的解析。直到脚本里的同步代码部分(settimeout等异步操作之外的代码)执行完之后,再接着解析接下来的HTML。
直到将整个HTML文档的最后一个标签解析完毕,DOM tree生成完毕。然后CSSOM tree 、render tree生成,开始渲染。

1. js加载会阻塞DOM树的解析和渲染

如果把js放在页面顶部,下载和解析js的时间里面,dom迟迟得不到解析和渲染,浏览器一直处于白屏,所以把JavaScript文件放在页面底部更有利于页面快速呈现。

2. css加载不会阻塞DOM树的解析但会阻塞DOM树的渲染

如果把css文件引用放在HTML文档的底部,浏览器为了防止无样式内容闪烁,会在css文件下载并解析完毕之前什么都不显示,这也就会造成白屏现象。(但是在firefox浏览器中测试,会出现样式闪烁,这也算是不同浏览器的权衡吧,要么等css全解析完一起显示,要么先显示然后css解析完再重新画上新样式)

当css文件放在<head>中时,虽然css解析也会阻塞后续dom的渲染,但是在解析css的同时也在解析dom,所以等到css解析完毕就会逐步的渲染页面了。

3. css加载会阻塞后面js语句的执行

因此,为了避免让用户看到长时间的白屏时间,我们应该尽可能的提高css加载速度,比如可以使用以下几种方法:

  1. 使用CDN(因为CDN会根据你的网络状况,替你挑选最近的一个具有缓存内容的节点为你提供资源,因此可以减少加载时间)
  2. 对css进行压缩(可以用很多打包工具,比如webpack,gulp等,也可以通过开启gzip压缩)
  3. 合理的使用缓存(设置cache-control,expires,以及E-tag都是不错的,不过要注意一个问题,就是文件更新后,你要避免缓存而带来的影响。其中一个解决防范是在文件名字后面加一个版本号)
  4. 减少http请求数,将多个css文件合并,或者是干脆直接写成内联样式(内联样式的一个缺点就是不能缓存)

defer和async

js加载会阻塞DOM树的解析和渲染,但<script> 标签的async和defer属性可以改变阻塞HTML解析的情况(但是较低版浏览器不支持,所以最佳的实践是,将<script>放在</body>前)。

async和defer对于内联JavaScript是无效的

defer
设置了defer的script外链文件,在下载js文件期间不会阻塞HTML的解析,而且等js下载完毕时若HTML还没解析完毕,js会等到HTML文档解析完毕后再执行。如果有多个js下载文件,那么执行时也是按照顺序执行。

async
设置了async的script外链文件,在下载js文件期间不会阻塞HTML的解析,但是js下载完毕之后就会立即执行,无论现在HTML是否正在解析。
在这里插入图片描述x

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猫老板的豆

你的鼓励将是我创作的最大动力~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值