前端--浏览器渲染页面的过程

首先浏览器会从HTTP服务器获取html文档,将文档渲染到页面呈现给用户需用经过以下几个步骤。

一. 解析文档构建DOM树

浏览器需要解析的内容可分为三个部分:

  • HTML/XHTML/SVG:解析后可生成DOM树
  • CSS:解析后可生成CSS规则树
  • JS:解析脚本,通过DOM API操作DOM树,通过CSSOM API操作CSS规则树,从而可以与用户进行交互

在解析文档构建DOM树时,有一定的执行顺序(前提是脚本文件标签不包含defer和async属性的情况下):

遇到html标签,会进行DOM树的构建
如果在构建DOM树的过程中遇到外联的脚本声明,会暂停对文档的解析,创建新的网络连接,下载相应的脚本文件
样式文件下载完毕后,会构建CSS规则树,脚本文件下载后,解释并立即执行。
在构建DOM的同时,结合CSS规则树完成页面的渲染
如果DOM树先于CSS规则树构造完成,则CSS规则树构建完成之后,页面会发生一次重绘,将新构建的CSS规则应用于渲染树
根据这个解析的过程,我们可以理解到为什么将CSS放在头部,JS放在尾部,可以实现页面优化?
一般加载CSS用href,放在头部,加载script用src,放在body内的下方。
CSS文件是并行下载,不会停止对当前文档的加载,而JS是异步,会停止当文档的渲染,先对该资源进行加载,完成之后才会继续对文档渲染。
CSS和DOM树是同步进行的,所以放在头部优先加载构建,如果放在后面,页面会发生重绘。放在前面也会减少白屏的时间。
JS可能改变DOM树的结构,所以需要一个稳定的DOM树,并且JS加载后立即执行,同时会阻塞后面的资源加载。如果JS是内联脚本,那么浏览器会先去执行这段,如果是外联,会先去加载脚本,然后执行,最后再继续解析HTML文档。

上述的执行顺序时不存在defer和async属性的情况下的,如果存在会对顺序有什么影响呢?
为了防止脚本加载是的浏览器页面阻塞,妨碍用户的体验。应该合理使用script标签的defer和async属性。这两个属性可以用于调整脚本的下载和执行顺序,从而可以使脚步不阻塞页面的加载。
defer:开启新的线程下载脚本文件,并且让脚本在文档解析完成后执行。

defer只适用于外联脚本,如果script标签没有指定的src属性,只是内联脚本,不要使用defer
如果有多个声明了defer的脚本,则会按顺序下载和执行。
defer脚本会在DOMContentLoaded和load事件之前执行
async:异步下载脚本文件,下载完毕立即解释执行代码。

只适用于外联脚本
如果有多个二声明了async的脚本,下载和执行都是异步的,不能确保彼此的先后顺序
async会在load事件之前执行,但并不能确保与DOMContentLoaded的执行先后顺序
二. 构建渲染树
当解析完文档之后,浏览器引擎会将CSS规则树附着到DOM树上,根据二者构造渲染树(Render Tree)
渲染树中没有Head、display:node之类的东西,但是DOM树中有
CSS规则树匹配到DOM树需要解析CSS的选择器,为了提高该过程的性能,DOM树应该尽量小,CSS选择器应该避免使用id 和 class,避免过度重叠。

三. 布局和绘制渲染树
布局:
解析position,overflow,z-index等属性,计算每一个渲染树节点的位置和大小。
绘制:
调用 操作系统的API完成绘制。

以上就是浏览器渲染页面的过程了
其中有几个重要的点需要单独拎出来讲一下:

1.回流与重绘

回流:
DOM结构中的各个元素都有自己的盒子模型,浏览器根据各种样式计算元素的尺寸和位置,构建渲染树的过程称之为回流。当渲染树节点的尺寸、布局、隐藏属性发生改变时,会触发回流操作,重新构建渲染树。每个页面在第一次加载的时候,都会发生回流。回流一定导致重绘。
重绘:
当各种盒子的位置、大小以及其他属性,例如颜色、字体大小等都确定下来后,浏览器便把这些元素都按照各自的特性进行绘制,于是页面的内容出现了,这个过程称之为repaint。

会触发reflow的操作
Reflow 的成本比 Repaint 的成本高得多。DOM Tree 里的每个结点都会有 reflow 方法,一个结点的 reflow 很有可能导致子结点,甚至父点以及同级结点的 reflow。在一些高性能的电脑上也许还没什么,但是如果 reflow 发生在手机上,那么这个过程是非常痛苦和耗电的。所以,下面这些动作会触发reflow操作,有很大可能会是成本比较高的。

增加、删除、修改 DOM 结点
移动 DOM 的位置
绘制动画
修改 CSS 样式
Resize 窗口的时候或是滚动
修改网页的默认字体
注:display:none 会触发 reflow,而 visibility:hidden 只会触发 repaint,因为没有发现位置变化

2.onload事件和DOMContentLoaded事件
DOMContentLoaded事件是当初始HTML文档完全被加载和解析(即所有的DOM完全解析)时触发的,无需要等待样式表,图片,子框架完成加载。而onload事件要等页面所有元素,包括图片以及脚本等全部加载完成才触发,因此它比DOMContentLoaded要更晚执行。
在页面的图片很多,网络不好的情况下,从用户访问到onload触发可能需要很长的时间,此时如果在onload中加入许多初始化的动作, 必然会影响用户的体验。这事使用DOMContentLoaded事件代替onload事件是更合适的。
 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值