HTML5:为什么脚本标签需要放在body结束标签之前而不是body开始标签之前?

12

在编写HTML页面时,一些网站建议将脚本写在BODY标签的末尾而不是写在开头。我看到过这样做可以提高页面刷新的性能。但是,当DOM解析所有标记后才呈现HTML页面时,这种方法如何帮助提高性能?


1
页面渲染比简单的线性进展要复杂得多。页面末尾的脚本不会“阻塞”先前的可视内容被渲染。 - isherwood
当 HTML 页面在 DOM 解析所有标签后才被渲染时,这是不正确的。 - Musa
更新于2022年,不必将脚本放在页面底部,紧挨着闭合的</body>标签前。这种方法已经过时了。请查阅deferasynctype='module' - Beki
3个回答

17

有一个惯例是将依赖项(如jQuery)放在head标签内。 然而,如果不将DOM加载到窗口中,则脚本无法访问它。

请查看以下示例:

<!DOCTYPE html>
<head>
   <script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js
   </script>
</head>

<script type="text/javascript">
   $('#appleTest').html("Apples are great.");
</script>

<body>
   <div id="appleTest">
   </div>
</body>
如果你运行这个代码,你将无法在浏览器窗口中看到“苹果很棒”的内容,因为jQuery选择器没有任何东西可以选择。 如果你将脚本移动到</body>标签下面,当jQuery选择器方法被调用时,它可以找到div,因为它已经被加载到窗口中。

请记住,DOM 操作只是 JavaScript 可能用途之一,而 JavaScript 的用途是无限的。 - ffflabs

11
JavaScript加载不是DOM的一部分,但它是阻塞的,直到完成加载才会中断加载过程。即使是一个小脚本,它仍然是额外的请求,并会减慢整个过程的速度。
事实上,浏览器只需要DOM结构就可以开始渲染。他们不需要脚本,也不计算布局。它们只是无用的负担,直到它们被执行。
即使CSS在初始渲染过程中被认为是不必要的(或多或少),但由于CSS加载是非阻塞的,这不是问题。
将脚本放在底部带来的性能提升可能会有所不同,即使这是推荐的做法,它也可能并不总是无害的。例如,在处理 CMSes 时,您可能会设计主题以在底部加载脚本,但您无法控制插件。例如,这在 WordPress 中经常发生,人们最终会将脚本放在头部以避免与插件冲突。 奖励曲目 当涉及到跟踪脚本,比如mixpanel、inspectlet,甚至是Google Analytics…你可能希望检测用户因为慢加载时间、成人广告拦截等原因,在进入你的页面后几秒钟就离开了。
如果你把跟踪脚本放在底部,它可能无法及时启动以检测该访问,因此你将不知道自己有这样极高的跳出率。在这种情况下,我会考虑把脚本放在头部。
如果你在开头放置资源提示,比如说:
<link rel="preconnect" href="https://api.mixpanel.com" />
<link rel="preconnect" href="https://cdn.mxpnl.com/" />

或者

<link rel="prefetch" href="https://cdn.mxpnl.com/libs/mixpanel-2-latest.min.js" as="script">

它可以减轻在 head 中加载这些脚本的缺点。

1
你能解释一下或者发一个链接来解释为什么“CSS加载是非阻塞的”吗? - dalvarezmartinez1
由于样式表和字体不会影响DOM的解析方式,它们只是用来为其添加样式。它们可以在加载后应用,就像渐进式渲染方法一样。它们在DOM树中被发现后才会被请求,但流程会继续进行而不必等待它们完成。 - ffflabs

2
这对于优化网页加载速度会有所帮助,因为浏览器解析DOM时,HTML页面并不是仅在DOM准备好后才被呈现。这意味着通过让浏览器最后加载脚本,即使DOM还没有准备好,你也可以实现更快的页面“加载”。用户可以看到您的页面,甚至与之交互,而在最后加载的那些脚本尚未加载完成。当然,如果您的页面都由脚本构建,则用户将不会看到太多内容。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接