JavaScript 执行是否推迟到 CSSOM 构建完成?
Is JavaScript execution deferred until CSSOM is built or not?
从 read/learned 关于 CSSOM 开始,直到今天,这个问题的答案对我来说都很清楚。我似乎无法找到最初的文章,但它通过示例非常清楚地解释了 JavaScript 执行被推迟,直到 CSSOM 从所有 <style>
和 <link>
标签构建在 <head>
中(不适用的除外,基于 @media
查询)。
或者至少那是我当时的看法,直到今天我都没有理由怀疑它。
这似乎得到了 Web 基础/性能 this sub-chapter 中粗体声明的支持,来自 Google:
... the browser delays script execution and DOM construction until it has finished downloading and constructing the 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 构建完成),页面会空白 10 秒,然后再构建 CSSOM 和执行 <script>
以评论 <link />
出来并允许页面呈现。
如果他是对的,那么 js 是 运行,因为它已经满足并且 <link />
请求永远不会离开,因为它现在是评论。
惊喜:
- 页面立即呈现。 他是对的!
- 但是
<link />
请求离开并且浏览器选项卡显示加载图标 10 秒。 我也是对的!还是我?我很困惑,我就是这样...
任何人都可以对此有所了解吗?这是怎么回事?
和document.write
有关系吗?
它与加载 .php
文件而不是 .css
文件有关吗?
如果有任何不同,我在 Chrome、Ubuntu 上进行了测试。
我恳请链接可靠的(重新)资源或提供 eloquent example/test 来支持您可能考虑提供的任何答案。
这句话是对的,但这意味着如果您先放置样式 sheet,然后放置脚本,则在下载并解析样式 sheet 之前,脚本不会执行。看这个例子:
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 并非针对所有样式 sheet 一次性完成,而是一个渐进的过程——当浏览器遇到样式 sheet 时,它会下载、解析并下一步移动。也可能浏览器首先列出所有 CSS 资源并将它们添加到下载队列,甚至在执行任何脚本之前。这可以解释为什么即使脚本注释了 link
标记也会发出请求。
从 read/learned 关于 CSSOM 开始,直到今天,这个问题的答案对我来说都很清楚。我似乎无法找到最初的文章,但它通过示例非常清楚地解释了 JavaScript 执行被推迟,直到 CSSOM 从所有 <style>
和 <link>
标签构建在 <head>
中(不适用的除外,基于 @media
查询)。
或者至少那是我当时的看法,直到今天我都没有理由怀疑它。
这似乎得到了 Web 基础/性能 this sub-chapter 中粗体声明的支持,来自 Google:
... the browser delays script execution and DOM construction until it has finished downloading and constructing the CSSOM.
然而,在我提供的
<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 构建完成),页面会空白 10 秒,然后再构建 CSSOM 和执行 <script>
以评论 <link />
出来并允许页面呈现。
如果他是对的,那么 js 是 运行,因为它已经满足并且 <link />
请求永远不会离开,因为它现在是评论。
惊喜:
- 页面立即呈现。 他是对的!
- 但是
<link />
请求离开并且浏览器选项卡显示加载图标 10 秒。 我也是对的!还是我?我很困惑,我就是这样...
任何人都可以对此有所了解吗?这是怎么回事?
和document.write
有关系吗?
它与加载 .php
文件而不是 .css
文件有关吗?
如果有任何不同,我在 Chrome、Ubuntu 上进行了测试。
我恳请链接可靠的(重新)资源或提供 eloquent example/test 来支持您可能考虑提供的任何答案。
这句话是对的,但这意味着如果您先放置样式 sheet,然后放置脚本,则在下载并解析样式 sheet 之前,脚本不会执行。看这个例子:
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 并非针对所有样式 sheet 一次性完成,而是一个渐进的过程——当浏览器遇到样式 sheet 时,它会下载、解析并下一步移动。也可能浏览器首先列出所有 CSS 资源并将它们添加到下载队列,甚至在执行任何脚本之前。这可以解释为什么即使脚本注释了 link
标记也会发出请求。