为啥在重新计算 chrome 开发工具中的样式之前评估过 js?

Posted

技术标签:

【中文标题】为啥在重新计算 chrome 开发工具中的样式之前评估过 js?【英文标题】:js evaluated before recalculating style in chrome dev tools why?为什么在重新计算 chrome 开发工具中的样式之前评估过 js? 【发布时间】:2021-08-05 20:06:20 【问题描述】:

article 表示 CSS 会阻塞渲染,因此 js 将在构建 CSSOM(也就是在开发工具中重新计算样式)后进行评估

但是,在 Chrome 开发工具中。看来js是在CSSOM之前评估的,为什么会这样呢?我误会了吗?

如果你想看我的例子 => here

调用树

事件日志

<html>
<head>
<style>
  h1 color:red;
  p>p color:blue;
  p>p>p color:blue;
  p>p>p>p color:blue;
  p>p>p>p>p color:blue;
  p>p>p>p>p>p color:blue;
  p>p>p>p>p>p>p color:blue;
  p>p>P>p>p>p>p>p color:blue;
</style>
</head>
<body>

<h1>A heading</h1>
<p>A paragraph.</p>
<p>Hello <span>web performance</span> students!</p>
    <div><img src="awesome-photo.jpg"></div>
    <script>
      var span = document.getElementsByTagName('span')[0];
      span.textContent = 'interactive'; // change DOM text content
      span.style.display = 'inline';  // change CSSOM property
      // create a new element, style it, and append it to the DOM
      var loadTime = document.createElement('div');
      loadTime.textContent = 'You loaded this page on: ' + new Date();
      loadTime.style.color = 'blue';
      document.body.appendChild(loadTime);
      var cnt=0
      while(cnt++ <=9999999) 
    </script>
</body>
</html>

【问题讨论】:

您正在使用“调用树”视图,它是按总时间排序的聚合视图。您应该使用按时间顺序显示事件的“事件日志”选项卡 【参考方案1】:

本文作者关注domContentLoaded 事件,或者在页面准备好呈现给用户的那一刻,不再出现白屏。当蓝色垂直线出现在时间线中时很重要。这是了解页面对用户可用的速度的重要事件。在内容出现之前,用户必须盯着白屏多长时间?

由于单页应用程序的出现,几乎所有内容只有在主脚本加载后才能使用。这就是为什么如此多的*** Web 应用程序首先使用服务器端呈现的页面,然后 javascript 控制单页应用程序。他们甚至使用代码拆分来加载当前页面所需的内容。

本文深入探讨了包含外部 CSS 和 js 文件的效果。这些文件的加载和解析如何推动domContentLoaded 事件,这意味着将白屏更改为内容会出现更多延迟,即使内容 (HTML) 已经解析并准备好呈现。

性能事件日志确实显示了正在发生的事情的详细信息,但如果您进一步向下滚动,您可以找到Event:readystatechangeEvent:pageshow,它们代表内容呈现给用户的时间戳。这些事件在脚本和样式计算之后。 &lt;script&gt; 行会阻止 domContentLoaded 事件,直到他可以完成他的事情。

这就是为什么建议在脚本标签中使用async 属性,这样它就不会阻塞白屏。想象一下,如果我们添加到网页的所有外部脚本也阻止了页面呈现。延迟对用户来说非常明显,以至于他/她可能会决定离开。

希望这能解释您的问题。

【讨论】:

【参考方案2】:

回答

我认为当您在 Chrome 和 IE11 中使用内联或解析器阻止脚本时会有一些优化

当我在 HTML 下测试时

<html>
<head>
<style>
  h1 color:red;
  p>p color:blue;
  p>p>p color:blue;
  p>p>p>p color:blue;
  p>p>p>p>p color:blue;
  p>p>p>p>p>p color:blue;
  p>p>p>p>p>p>p color:blue;
  p>p>P>p>p>p>p>p color:blue;
</style>
</head>
<body>

<h1>A heading</h1>
<p>A paragraph.</p>
<p>Hello <span>web performance</span> students!</p>
    <div><img src="awesome-photo.jpg"></div>
    <script>
      var span = document.getElementsByTagName('span')[0];
      span.textContent = 'interactive'; // change DOM text content
      span.style.display = 'inline';  // change CSSOM property
      // create a new element, style it, and append it to the DOM
      var loadTime = document.createElement('div');
      loadTime.textContent = 'You loaded this page on: ' + new Date();
      loadTime.style.color = 'blue';
      document.body.appendChild(loadTime);
      var cnt=0
      while(cnt++ <=9999999) 
    </script>
</body>
</html>

IE11 显示预期顺序,但并行执行。 HTML 解析 => CSSOM => 评估脚本

另一方面,Chrome 显示意外顺序 HTML Parsing => evalute script => CSSOM

所以我将内联脚本更改为外部脚本,现在 Chrome 按预期顺序运行 HTML Parsing => CSSOM => 评估脚本

<html>
<head>
<style>
  h1 color:red;
  p>p color:blue;
  p>p>p color:blue;
  p>p>p>p color:blue;
  p>p>p>p>p color:blue;
  p>p>p>p>p>p color:blue;
  p>p>p>p>p>p>p color:blue;
  p>p>P>p>p>p>p>p color:blue;
</style>
</head>
<body>

<h1>A heading</h1>
<p>A paragraph.</p>
<p>Hello <span>web performance</span> students!</p>
    <div><img src="awesome-photo.jpg"></div>
</body>
<script src="test.js"></script>
</html>

优化的工作原理

当您有内联脚本时,即使它不操作您的 DOM 或 CSSOM,它也会比重新计算样式执行得更快,然后在 Chrome 和 IE11 中完成 HTML 解析后,重新计算样式将再执行一次。

<html>
<head>
<style>
  h1 color:red;
  p>p color:blue;
  p>p>p color:blue;
  p>p>p>p color:blue;
  p>p>p>p>p color:blue;
  p>p>p>p>p>p color:blue;
  p>p>p>p>p>p>p color:blue;
  p>p>P>p>p>p>p>p color:blue;
</style>
</head>
<body>

<h1>A heading</h1>
<p>A paragraph.</p>
<p>Hello <span>web performance</span> students!</p>
    <div><img src="awesome-photo.jpg"></div>
    <script>
      var cnt=0
      while(cnt++ <=9999999) 
    </script>
</body>
<!-- <script src="test.js"></script> -->
</html>

【讨论】:

以上是关于为啥在重新计算 chrome 开发工具中的样式之前评估过 js?的主要内容,如果未能解决你的问题,请参考以下文章

Chrome 开发者工具样式选项卡显示褪色的 CSS 定义,为啥?

如何强制 linux 上的 chrome 重新计算/重新渲染 ":hover" 样式?

为啥 chrome 样式检查器显示来自 .scss 的样式?

为啥用户代理样式表会覆盖我的样式? [关闭]

Chrome中单个帧中的重复事件

Flexbox 不会重新计算样式