正在测试CSS会不会阻塞DOM解析,这里模拟样式延时加载:
<link rel="stylesheet" type="text/css" href="style.php">
<?php
// 通过PHP模拟样式延时加载
sleep(5);
header('Content-Type: text/css');
echo 'div{color: red}';
当分别在谷歌和火狐上运行时,DOMContentLoaded的执行不一样。
谷歌:
火狐:
通过上面的测试,是不是可以说明在谷歌浏览器上会阻塞,而在火狐上不阻塞。
或是不同的内核有不同的机制?
DOMContentLoaded
影响,所以可能在这里表现没什么差异,于是开发商就不是很关注
首先来看标准https://html.spec.whatwg.org/...
标准里写得比较清楚。
DOMContentLoaded
事件的触发取决于文档准备状态的变化,它是在2个状态之间的(即不是即时的)。当DOMContentLoaded
触发时,所有除了异步脚本元素<script async />
的子资源都应该已经加载完了。根据以上描述,
DOMContentLoaded
事件应该在样式表被加载完才触发。但我们去查询标准的变更历史可以发现,这段标准描述存在了非常长的时间。浏览器的发展是非常迅速的,虽然标准本身的描述(不知道什么原因)未经过改变,但至少浏览器都是希望能够尽快尽早地允许开发者进行交互。在标准中的流程描述部分,也未提到
DOMContentLoaded
事件的具体触发时机,所以就取决于各内核中自身实现的差异了。其实这个问题一直都是存在的,而且各版本的内核处理起来可能不尽相同。一些实验表明,如果一个网页文档只加载了样式表,那么样式表的加载就不会阻塞
DOMContentLoaded
事件的触发;而当样式表引用之后紧跟(同步)脚本时,会阻塞DOMContentLoaded
事件的触发。这看起来更像是浏览器为了优化,而在仅加载样式表的情况下,提前触发了
DOMContentLoaded
事件;或进一步说明DOMContentLoaded
事件的触发,是和脚本息息相关的。后一种推断似乎更为可靠,因为标准中关于DOMContentLoaded
事件的描述中明确提到相关的就是脚本。从工作机制上,我们也不难推测出,当仅有样式表需要加载时,网页文档可以先行被解析成DOM树,因为样式表对应的解析成CSSOM的过程与DOM解析过程相互独立,只在最后合成阶段有关系,所以可以并行进行。但当样式表之后有脚本需要执行时,因为脚本可能修改DOM或者需要获取DOM上的样式,所以必须依赖DOM树和CSSOM树全部解析完成(且关联)。因此,如果样式表的加载后如果跟了脚本,就一定会使得DOMContentLoaded延后。