1

domLoading

浏览器开始解析dom树的时间点

domInteractive

表示浏览器已经解析好dom树了。

domContentLoaded

同步的JS已经执行完毕了。

这里需要再解释一点:

  • 由于同步JS会阻塞Dom的解析,因此在有同步JS的情况下,domInteractive和domContentLoaded的区别不大。

  • 如果JS添加了defer属性,那么domInteractive和domContentLoaded的时间差取决于JS的下载和执行时间。defer JS表示告诉浏览器,这段JS在domInteractive后执行。见http://www.w3.org/TR/html5/syntax.html#the-end 。一旦执行完defer JS,就会触发domContentLoaded.

  • 如果JS属性为async,那么domContentLoaded和domInteractive又几乎没什么区别了,因为js的解析不会阻塞dom,也不阻塞domContentLoad事件。

onload

页面上的元素已经加载完毕了。包括所有CSS, JS, Image等等。

一些小实验

以下示例均采用blocking做实验,可以访问在线版

疑问1:同步的JS通过document.write写入JS script会不会延迟DomContentLoaded?

结论:会。从例子中可以看到,DomContentLoaded必须等到同步写入的JS文件写完才触发。

代码:

<html>
<head>
</head>
<body>
  <script>
  document.write('<script src="t/wait-3s.js"' + '></' + 'script>');
  </script>
  {{flush 1000}}
  <h1>Hello World</h1>
</body>
</html>

时间线:

clipboard.png

疑问2: 同步的JS动态插入defer JS会不会延迟DomContentLoaded?

结论:不会延迟comContentLoaded,但会阻塞onload的时间。需要补充的是,即便是动态插入没有defer的JS,也不会延迟DomContentLoaded.

对于如下代码:

<html>
<head>
</head>
<body>
  <script>
   var script = document.createElement('script');
   script.src= "/t/wait-2s.js";
   script.defer = true;
   document.head.appendChild(script);
  </script>
  {{flush 1000}}
  <h1>Hello World</h1>
</body>
</html>

时间线如下:(蓝色为主文档,黄线为JS文件)

clipboard.png

疑问3:如果在domContentLoaded的时刻动态插入(同步/defer/async)的script,会不会阻塞onload事件?

结论:(同步/defer/async)均会阻塞onload事件。

代码(以defer为例):

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
</head>
<body>
  <script>
   document.addEventListener('DOMContentLoaded', function(){
     var script = document.createElement('script');
     script.src= "/t/wait-2s.js";
     script.defer = true;
     document.head.appendChild(script);
   });
  </script>
  {{flush 1000}}
  <h1>Hello World</h1>
</body>
</html>

时间线:

clipboard.png

上面的两个小实验应证的是规范中的:Spin the event loop until the set of scripts that will execute as soon as possible and the list of scripts that will execute in order as soon as possible are empty.

疑问三:如果在domContentLoaded时动态插入CSS/图片/iframe,会阻塞onload事件吗?

结论:会阻塞。动态插入的图片/CSS会阻塞onload事件,iframe不会。

代码(以image为例):

<html>
<head>
</head>
<body>


<script>
   document.addEventListener('DOMContentLoaded', function(){
     
     var img = document.createElement('img');
     img.src= "/t/wait-2s.png";
     document.body.appendChild(img);
     

     /*
     var link = document.createElement('link');
     link.rel = "stylesheet";
     link.href = "t/wait-3s-red.css";
     document.body.appendChild(link);
     */

     /*
     var iframe = document.createElement('iframe');
     iframe.src = "t/wait-3s.html";
     document.body.appendChild(iframe);
     */

     
   });
  </script>



  {{flush 1000}}


<h1>Hello World</h1>


</body>
</html>

结果:

clipboard.png

【更多待补充...】


ssnau
1.5k 声望98 粉丝

负能量职业打码师