5

自从我阅读/了解 CSSOM 到今天,这个问题的答案对我来说一直很清楚。我似乎无法找到最初的文章,但它通过示例非常清楚地解释了 JavaScript 执行被推迟到 CSSOM 从所有<style><link>标签中构建<head>(除了那些不应用的标签之外,基于@media查询)。
或者至少我当时是这么认为的,直到今天我都没有理由怀疑它。

这似乎得到了Google 在 Web Fundamentals / Performance分章中粗体声明的支持:

...浏览器延迟脚本执行和 DOM 构建,直到它完成下载和构建 CSSOM。

但是,在我提供的这个答案下,与另一个 SO 用户就该主题进行了友好的聊天,这一说法受到了严重挑战,他在其中提出了以下建议来证明相反的情况:

<head>
  <script>document.write("<!--");</script>
  <style> body { background-color: red; } </style>
  -->
</head>

好的,让我们确定一下。让我们<style>

<link rel="stylesheet" type="text/css" href="test.php" />

...并test.php挂起几秒钟:

<?php
sleep(10);
header('Content-Type: text/css');
?>

/* adding styles here would be futile */

如果我是对的(并且js执行被推迟到 CSSOM 构建完成),页面会在构建 CSSOM 之前和执行之前暂停 10 秒,<script>这将注释掉<link />并允许页面呈现。

如果他是对的,那么 js 会在满足时运行,并且<link />请求永远不会离开,因为它现在是一个评论。

惊喜:

  • 页面立即呈现。他是对的!
  • <link />请求离开,浏览器选项卡显示加载图标 10 秒。我也对!还是我?我很迷茫,这就是我...

任何人都可以对此有所了解吗?到底是怎么回事?
有关系document.write吗?
它与加载.php文件而不是加载文件有关.css吗?


如果有什么不同,我在 Ubuntu 上的 Chrome 中进行了测试。

我恳请链接一个可靠的(重新)来源或提供一个雄辩的示例/测试来备份您可能考虑提供的任何答案。

4

1 回答 1

3

这句话是对的,但这意味着如果您先放置样式表,然后再放置一个脚本,则该脚本将在样式表下载并解析之前不会执行。看这个例子:

test.php

<?php
sleep(5);
header('Content-Type: text/css');
echo 'body {background-color: red;}';

index.html

<link rel="stylesheet" href="test.php">
<script>console.log('done');</script>

console.log背景颜色变为红色之前不会执行调用。

这导致了一个结论,即构建 CSSOM 并不是对所有样式表都完成一次,而是一个渐进的过程——当浏览器遇到一个样式表时,它会下载它、解析并移动下一步。也可能浏览器首先列出所有 CSS 资源并将它们添加到下载队列中,甚至在执行任何脚本之前。这可以解释为什么即使link标签被脚本注释了也会发出请求。

于 2017-06-05T20:25:41.977 回答