【问题标题】:Why google is using the term "Render-Blocking JavaScript"?为什么 google 使用术语“Render-Blocking JavaScript”?
【发布时间】:2018-04-11 06:01:05
【问题描述】:

见:

https://developers.google.com/speed/docs/insights/BlockingJS

Google 在那里谈论“Render-Blocking JavaScript”,但在我看来,这个术语是不正确、令人困惑和误导的。好像“谷歌”也看不懂了吧?

这一点是 Javascript 执行总是暂停/阻塞渲染,也总是暂停/阻塞“HTML 解析器”(至少在 Chrome 和 Firefox 中)。如果是外部 js 文件,结合异步脚本标签,它甚至会阻止它!

因此,通过例如使用异步来删除“阻止渲染的 Javascript”,意味着也存在非阻塞 Javascript,或者“异步 Javascript 执行”不会阻止渲染,但事实并非如此!

正确的术语是:“渲染阻止下载”。使用 async 可以避免:下载 js 文件,不会暂停/阻止渲染。但是执行还是会阻塞渲染。

另一个例子证实 Google 似乎没有“理解”它。

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Test</title>
</head>
<body>
    Some HTML line and this is above the fold
    <script>
        // Synchronous delay of 5 seconds
        var timeWhile = new Date().getTime(); 
        while( new Date().getTime() - timeWhile < 5000 );
    </script>
</body>
</html>

我在 Firefox 和 Chrome 中对其进行了测试,它们在 5 秒后而不是在 5 秒内显示(渲染):“一些 HTML 行,这是首屏”!!!!看起来 Google 认为在这种情况下,Javascript 不会阻塞渲染,但正如理论上所预期的那样,它会阻塞。在开始执行 js 之前,所有的 html 都已经在 DOM 中(除了 end body / html 标签),但是渲染还没有完成,将被暂停。因此,如果 Google 真的意识到了这一点,那么 Chrome 会在开始执行 javascript 之前先完成渲染。

如果您采用上面的示例并且您正在使用:

<script src="delay.js" async></script>

<script src="delay.js"></script>

而不是内部 javascript。然后它也可以给出与上面示例相同的结果。例如:

  • 如果预加载器(扫描已下载的文件)已经下载了“delay.js”,则在“HTML 解析器”出现在 Javascript 部分之前。
  • 通常来自 Google、Facebook 等的外部文件已存储在缓存中,因此无需下载,它们只是从缓存中获取文件。

在这种情况下(以及异步),结果将与上面的示例相同(至少在很多情况下)。因为如果没有额外的下载时间,“Javascript 执行”将/可以在前面的 html 完成渲染之前开始。

因此,在这种情况下,您甚至可以考虑在 delay.js 上添加“no-cache”/“no-store”(甚至额外延迟),以使您的页面渲染得更快。通过强制下载(或额外延迟),您将给浏览器一些额外的时间来完成前面的 html 的渲染,然后再执行渲染阻塞 Javascript。

所以我真的不明白为什么 Google(和其他人)使用术语“渲染阻止 JavaScript”,而从理论和“现实生活”示例来看,它看起来像是错误的术语和错误的想法。我看网上没有人讨论这个,所以我不明白。我知道我很聪明(j/k),但我觉得有点奇怪,成为唯一一个有上述想法的人。

【问题讨论】:

  • 从您链接到的页面:内联脚本总是被解析器阻塞,除非您编写额外的代码来延迟它们的执行。
  • @JoshLee 但这也不是真的。 Javascript 执行,总是解析器阻塞。如果是异步/同步/延迟也没关系。所以这就是为什么谷歌用他们的信息混淆人们,正如你所看到的,现在你也因为他们的信息而思考错误的方式。您可以使用带有 defer 的外部脚本标记进行我的测试,并且在缓存的情况下(因此没有下载时间):“一些 HTML 行,这在折叠之上”在 5 秒后再次显示,因为在 js 执行期间渲染被阻止!

标签: javascript google-chrome asynchronous rendering render-blocking


【解决方案1】:

我与 Chrome、Firefox、Safari 和 Edge 的开发人员一起工作,我可以保证从事浏览器这些方面工作的人理解async/defer 之间的区别。您可能会发现,如果您礼貌地提问,其他人会对您的问题做出更有礼貌的反应。

这是来自HTML spec 的关于脚本加载和执行的图片:

这表明如果经典脚本既没有async 也没有defer,则在提取期间发生阻塞。它还表明执行总是会阻塞解析,或者肯定会阻塞解析的可观察效果。这是因为 DOM 和 JS 在同一个线程上运行。

我在 Firefox 和 Chrome 中对其进行了测试,它们在 5 秒后而不是在 5 秒内显示(渲染):“一些 HTML 行,这是首屏”!!!!

浏览器可能会呈现上面的行,但不会呈现下面的内容。上述行是否渲染取决于事件循环在屏幕刷新方面的时间。

Google 似乎认为在这种情况下,Javascript 不会阻止渲染

我正在努力寻找对此的参考。您在给我的电子邮件中linked to my article,专门谈到了在获取期间渲染被阻止。

在这种情况下(以及异步),结果将是相同的

规范不保证这一点。您依赖于即时从缓存中检索,但情况可能并非如此。

在这种情况下,您甚至可以考虑将“no-cache”/“no-store”放在 delay.js(甚至额外的延迟)上,以使您的页面渲染得更快。通过强制下载(或额外延迟),您将给浏览器一些额外的时间来完成前面的 html 的渲染,然后再执行渲染阻塞 Javascript。

在这种情况下为什么不使用defer?它在没有带宽损失和不可预测性的情况下实现了相同的效果。

【讨论】:

  • 我很礼貌地问了这个问题,但我不能说我认为谷歌似乎错了。我不骂人,我只是在争论。但无论如何,非常感谢您的回复!我真的很感激!尽管我仍然没有答案;)。 Firstable 在我的邮件中,我不是在谈论“在获取期间渲染被阻止”。我说的是为什么 Chrome 在开始执行 javascript 之前没有完成对前面的 html 的渲染。
  • 您说:“您依赖于即时从缓存中检索,但情况可能并非如此。”。我说“将/可以”,所以我知道这一点,但我依赖于我所做的测试。您可以使用我的示例进行测试,然后使用异步脚本标记。然后你会发现,在这种情况下,“javascript 执行”会阻止“前面的 html”的呈现。因此,一个选项是不缓存它,以给浏览器一些额外的时间来完成前面的 html 的呈现。
  • 无论如何,也许你可以告诉我为什么 Chrome 没有完成渲染,然后再执行我给出的示例中的 javascript?我看不出有什么理由。然后你可以说你可以假设人们理解它,但是我不明白为什么 Chrome 会这样做,直到现在我无法得到这个问题的任何答案。只有那些只是说“谷歌永远是对的”而没有任何论据/答案的人。这就是我沮丧的来源。而且您不认为“Render-Blocking JavaScript”这个术语令人困惑吗?
  • 哦,还有一件事。关于你的延迟建议......我很抱歉地说,我并不是说它不好,但看起来你真的不明白我的观点和问题。因为使用 defer,javascript 执行也会阻塞渲染。因此,例如在缓存的情况下,可以在完成前面的 html 渲染之前执行 javascript,因此它仍然是阻塞渲染。测试(使用延迟)将给出与我展示的内联/异步/同步等示例相同的结果。所以 5 秒后你会看到一些东西。
【解决方案2】:

Maarten B,我确实测试了你的代码,你确实是正确的。无论您使用异步、延迟还是其他方式,内联 JavaScript 上方的行都不会被渲染。因此,Google 文档中的信息不正确。

【讨论】:

  • 您认为哪个文档不正确?
猜你喜欢
  • 2013-12-13
  • 1970-01-01
  • 1970-01-01
  • 2021-12-04
  • 2014-12-03
  • 2021-05-06
  • 2015-05-29
  • 1970-01-01
  • 2022-08-05
相关资源
最近更新 更多