-3

看:

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

谷歌在那里谈论“Render-Blocking JavaScript”,但在我看来,这个术语是不正确的、令人困惑的和误导的。这几乎看起来像“谷歌”也是不理解吗?

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

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

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

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

<!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 完成渲染之前开始。

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

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

4

2 回答 2

1

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

这是HTML 规范中关于脚本加载和执行的图像:

脚本加载示意图

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

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

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

看起来 Google 认为在这种情况下,Javascript 不会阻止渲染

我正在努力寻找对此的参考。您在发送给我的电子邮件中链接到我的文章,其中专门谈到了在获取期间渲染被阻止。

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

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

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

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

于 2017-10-30T17:39:13.643 回答
0

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

于 2017-10-30T18:33:33.707 回答