浏览器的渲染阻塞与优化

大家都知道,css文件放头部,js文件放body最底部,可是大家知道其中的原理吗?
要明白上述问题,我们需要知道是什么在阻塞页面的渲染?
一:回顾浏览器渲染流程

1.浏览器开始解析目标HTML文件,执行流的顺序为自上而下。

2.HTML解析器将HTML结构转换为基础的DOM(文档对象模型),构建DOM树完成后,触发DomContendLoaded事件。

3.CSS解析器将CSS解析为CSSOM(层叠样式表对象模型),一棵仅含有样式信息的树。

4.CSSOM和DOM开始合并构成渲染树,每个节点开始包含具体的样式信息。

5.计算渲染树中个各个节点的位置信息,即布局阶段。

6.将布局后的渲染树显示到界面上。

二:CSS是否会阻塞DOM的解析?

由上文可见,DOM树解析跟CSSOM解析,是互不影响的,两个并行过程,因此,CSS不会阻塞DOM的解析。
三:CSS是否会阻塞DOM的渲染?
根据以上的流程,可以知道,当cssom还没构建完成时,页面是不会渲染到浏览器界面的(渲染时需等css加载完毕,因为render树需要css信息),因此CSS会阻塞DOM的渲染。

其实我觉得,这可能也是浏览器的一种优化机制。因为你加载css的时候,可能会修改下面DOM节点的样式,如果css加载不阻塞DOM树渲染的话,那么当css加载完之后,DOM树可能又得重新重绘或者回流了,这就造成了一些没有必要的损耗。所以我干脆就先把DOM树的结构先解析完,把可以做的工作做完,然后等你css加载完之后,在根据最终的样式来渲染DOM树,这种做法性能方面确实会比较好一点。
**四:CSS是否会阻塞后续JS语句的执行?
会影响到js脚本的执行。因为js脚本不仅可以读取修改到dom,也可以读取修改到cssom。故在js脚本执行前,browser必须保证到css文件完全加载并解析完成,即cssom树完全构建好。这就导致了js执行的延迟,也因此导致html解析和渲染延迟。
(这就是css阻塞js执行,阻塞渲染的根本原因)
五:一些解决方法
1、在引入顺序上,css资源的引入要优于js脚本的引入
2、对css进行精简并尽快提供
3、可以用媒体类型(会加载不会阻塞)
4、用媒体查询(会记载,只有在符合的设备上才会进行阻塞)

<link href="style.css" rel="stylesheet"> 
<link href="style.css" rel="stylesheet" media="all"> 
<link href="portrait.css" rel="stylesheet" media="orientation:portrait"> 
<link href="print.css" rel="stylesheet" media="print">

第一个声明阻塞渲染,适用于所有情况。

第二个声明同样阻塞渲染:“all”是默认类型,如果您不指定任何类型,则隐式设置为“all”。因此,第一个声明和第二个声明实际上是等效的。

第三个声明具有动态媒体查询,将在网页加载时计算。根据网页加载时设备的方向,portrait.css 可能阻塞渲染,也可能不阻塞渲染。

最后一个声明只在打印网页时应用,因此网页首次在浏览器中加载时,它不会阻塞渲染。

最后,请注意“阻塞渲染”仅是指浏览器是否需要暂停网页的首次渲染,直至该资源准备就绪。无论哪一种情况,浏览器仍会下载 CSS 资源,只不过不阻塞渲染的资源优先级较低罢了。,然而这些等待的时间是完全不必要的。
注意:
与 同时在头部的话, 在上可能会更好。因为link在上的话,浏览器会先加载css,而后面body里的内容会被前面的js阻塞,原本body中的图片是可以和css并行加载的,现在只能等css执行完,js执行完,在执行(不太确定)。不过只是可能,是因为如果 的内容下载更快的话,是没影响的,但反过来的话, JS 就要等待了

六:js加载是否影响DOM的解析和渲染、js执行、css加载?(全部都影响)

  • 通俗的原理:浏览器并不知道脚本的内容是什么,如果先行解析下面的DOM,万一脚本内全删了后面的DOM,浏览器就白干活了。更别谈丧心病狂的document.write。浏览器无法预估里面的内容,那就干脆全部停住,等脚本执行完再干活就好了。

JS的阻塞
1、所有浏览器在下载JS的时候,会阻止其他的一切活动(比如其他资源的下载,内容的呈现等等)。为了提高用户体验,新一代浏览器都支持并行下载JS,但是JS下载还是会阻止其他资源的加载(图片、css文件等等)

2、原因:浏览器为了防止出现JS修改DOM树,需要重构DOM树的情况,就会阻止其他资源的下载和呈现

3、嵌入JS会阻止所有内容的呈现,但是外部JSD只会阻止其后内容的显示
(因为嵌入js是不需要加载直接可以执行的)
4.浏览器遇到 <script> 标签时,会触发页面渲染,这也就解释了上文中为什么js要等到css加载完。因为浏览器不知道脚本里面是什么,所以在脚本之前会先渲染一次页面,(cssom和dom tree合成render tree),确保脚本能获取到最新的dom信息,尽管可能js并不需要。

七:对于js阻塞,有两种解决方法
defer(延迟执行)async(异步执行)。这两种方法只适合与引入式的js脚本,不适合inline-script。

defer属性()
(这是延迟执行引入的js脚本(即脚本加载是不会导致解析停止,等到document全部解析完毕后,defer-script也加载完毕后,在执行所有的defer-script加载的js代码,再触发Domcontentloaded)

async属性()
(1)这是异步执行引入的js脚本文件
(2)与defer的区别是async会在加载完成后就执行,但是不会影响阻塞到解析和渲染。但是还是会阻塞load事件,所以async-script会可能在DOMcontentloaded触发前或后执行,但是一定会在load事件前触发。

引用(抄袭)的内容:
————————————————
版权声明:本文为CSDN博主「lulucong6」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/lucaslow/article/details/78307396

作者:陈纪庚
链接:https://juejin.im/post/5b88ddca6fb9a019c7717096
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

原文链接:https://blog.csdn.net/a409051987/article/details/72231008

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值