在正文标记的末尾呈现阻塞 Javascript - Firefox 呈现一些视觉内容,Chrome 不呈现
Posted
技术标签:
【中文标题】在正文标记的末尾呈现阻塞 Javascript - Firefox 呈现一些视觉内容,Chrome 不呈现【英文标题】:Render blocking Javascript at end of body tag - Firefox renders some visual content, Chrome does not 【发布时间】:2020-04-15 11:50:53 【问题描述】:我只是在试验一些与性能相关的优化。
据我了解,任何内联script
都会阻塞渲染,浏览器会在遇到它时立即执行它。它还会停止 DOM 解析。
所以,我希望 body
末尾的内联脚本会阻止渲染,并且浏览器在我关闭警报之前根本不会显示任何内容。
Chrome似乎按照上面的理解进行渲染,但是Firefox先渲染html然后显示alert。
这可能是什么原因?这是否意味着 Firefox 没有考虑将 javascript 渲染阻塞?或者渲染在 Chrome 和 Firefox 中是否意味着其他东西? Firefox 是否通过了解脚本接近 body
的事实进行优化?
这是代码:
<html>
<head></head>
<body>
<div>Some Content</div>
<div>Some Content</div>
<div>Some Content</div>
<div>Some Content</div>
<div>Some Content</div>
<div>Some Content</div>
<div>Some Content</div>
<div>Some Content</div>
<div>Some Content</div>
<div>Some Content</div>
<div>Some Content</div>
<div>Some Content</div>
<div>Some Content</div>
<script>
alert('here');
</script>
</body>
</html>
Chrome 版本:78 火狐版本:70
另一个观察结果是,如果警报在内联脚本与外部脚本中,chrome 的行为会有所不同。它阻止内联脚本中的警报,但不阻止外部脚本中的警报。
更新:后续问题:render-blocking Javascript at end of body tag - inline vs external script
【问题讨论】:
请不要更新问题以合并答案,这不是 SO 的工作方式。您最初的问题是关于阻止alert
,这是已回答的。更新问题以提出有关外部脚本的新问题会使问题成为移动目标。
实际的问题是关于脚本是否呈现阻塞以及浏览器如何处理它。还没有回答,但是我已经包含了与警报使用相关的更新。我知道随着更新它已经变得广泛。
好吧,我们不同意。我不会回答这个问题。但我能够回答它曾经是什么。没什么大不了。 :-)
是的,谢谢你的回答。我可能会根据调查结果提出另一个后续问题。其他人会更容易回答,否则这个问题可能会变得太宽泛。
这是后续问题:***.com/questions/59471566/…
【参考方案1】:
alert
不是检查渲染行为的好工具。浏览器越来越多地使 alert
及其近亲减少阻塞(不仅仅是 Firefox,Chrome 也在这样做,但尽管有很多重叠,但它们可能会做不同的事情;您可以阅读 Chrome 的方法 here)。
显然,Firefox 允许渲染继续进行,但 Chrome 不在这种特定情况下。
要检查渲染行为,您需要使用不是 1990 年代遗留下来的阻塞。 :-) 我使用的一种方法(虽然不是最近)是加载一个需要很长时间才能加载的脚本。 (您可以通过使用在进程中引入人为延迟的服务器端代码发送脚本的本地服务器来做到这一点。)
【讨论】:
谢谢!这很有意义。 将警报更改为长时间运行的循环似乎会在循环运行时阻止所有浏览器上的渲染,但更改为外部脚本似乎不会阻止渲染。浏览器在渲染阻塞方面处理外部脚本与内联脚本是否不同? @gaurav5430 - 恐怕我不知道。 :-) 他们会在网络操作期间继续渲染对我来说是有意义的,即使这意味着如果脚本使用document.write
可能会重新渲染,但我不能说我知道 没错。
另一个观察结果是,如果警报在内联脚本与外部脚本中,chrome 的行为会有所不同。它阻止内联脚本中的警报,但不阻止外部脚本中的警报。【参考方案2】:
渲染阻塞是指“阻塞在之后的任何渲染”。
这就是将 JavaScript 放在页面底部的原因——因此它不会阻止页面上方的任何呈现。现在我们当然有 async
和 defer
来帮助解决这个问题,但最初我们没有。
【讨论】:
所以您是在建议在 Javascript 执行之前呈现任何内容?不知道为什么,但这似乎不会发生在带有长“for”循环的内联脚本标记中。脚本运行,然后浏览器呈现 html。 (但如果同一段代码在外部脚本中,浏览器会在脚本执行之前渲染html) 这是后续问题:***.com/questions/59471566/… @gaurav5430 - “不知道为什么,但是对于带有长 'for' 循环的内联脚本标记似乎不会发生这种情况。” 因为在许多浏览器中,同一个线程做 JavaScript 也是处理绘制 DOM。如果该线程很忙,则不会绘制 DOM。但该线程不用于网络请求,仅用于完成它们。 @TJCrowder 这很有意义,并且还暗示了为什么外部脚本可能不会呈现阻塞,因为在这种情况下,线程将有时间在处理下载的 javascript 之前进行呈现,但内联它不会。这也意味着“在此之后阻止任何呈现”的声明可能不适用于所有浏览器,因为如果同一个线程正在执行下一行 javascript,则实际上会阻止呈现。 @gaurav5430 - 非defer
/async
脚本阻止渲染以下内容,因为它们可能使用document.write
。这是主要原因,也是async
存在的原因。 async
基本上是承诺不使用document.write
。从here 向下滚动一点,您将看到关于async
、defer
和type="module"
如何影响脚本加载和执行的有用图表。以上是关于在正文标记的末尾呈现阻塞 Javascript - Firefox 呈现一些视觉内容,Chrome 不呈现的主要内容,如果未能解决你的问题,请参考以下文章
似乎无法在 HTMLBody 末尾添加换行符(<br /> 标记被修剪)