HTML 中的 < script > 标记位置是否会影响网页的性能?

如果脚本标签位于 HTML 页面正文的上方或下方,这对网站的性能有影响吗?

如果像这样在两者之间使用:

<body>
..blah..blah..
<script language="JavaScript" src="JS_File_100_KiloBytes">
function f1() {
.. some logic reqd. for manipulating contents in a webpage
}
</script>
... some text here too ...
</body>

还是这样更好:

<script language="JavaScript" src="JS_File_100_KiloBytes">
function f1() {
.. some logic reqd. for manipulating contents in a webpage
}
</script>
<body>
..blah..blah..
..call above functions on some events like onclick,onfocus,etc..
</body>

还是这个:

  <body>
..blah..blah..
..call above functions on some events like onclick,onfocus,etc..
<script language="JavaScript" src="JS_File_100_KiloBytes">
function f1() {
.. some logic reqd. for manipulating contents in a webpage
}
</script>
</body>

不用说一切都是在 <html>的标签里! !

加载时如何影响网页的性能? 是否真的如此? 哪一个是最好的,要么在这三个或其他你知道的?

还有一件事,我在谷歌上搜索了一下,从这里开始: 加速您的网站的最佳实践,它建议使用 把脚本放在底部,但是传统上很多人把它放在 <head>标签中,它在 <body>标签之上。我知道这不是一个规则,但很多人更喜欢这样。如果你不相信,只是 视图来源的这一页!告诉我什么样的风格才是最好的表现。

77948 次浏览

文档顶部的脚本元素可以更快地使用(因此您可以绑定事件处理程序,并在元素可用时立即运行 JS) ,但是它们会阻塞页面其余部分的解析。

底部的脚本元素不是(所以您不能) ,并且没有任何重要的页面留下,所以是否阻塞也没有关系。

哪个是 最好的取决于相对的 重要性优先级(必须根据具体情况确定) ,即 JS 运行与 HTML 呈现的优先级。

请注意,底部的 script 元素必须出现 在里面 body 元素,因此它应该是:

<script>...</script></body></html>

而不是

</body><script>...</script></html>

脚本本身的性能肯定是相同的。

不过,正如您链接的文章中所解释的那样,位置非常重要,因为当浏览器遇到并加载 <script>标记的内容时,它会“暂停”(或“冻结”)页面的同步下载和呈现。因此,最好让浏览器呈现页面并应用 CSS 样式,而 那么包含您的 .js。它将看起来更顺利的用户。

另外,在底部包含脚本可能意味着在关闭 <body>标记之前。

是的,这确实会影响网页载入的效能。

问题是,普通的 <script>标记被阻塞了,所以 script 标记之后的所有内容都必须等到 script 标记完成加载和解析之后才能加载页面的其余部分。

现在有人可能会注意到,如果在脚本标记中使用 async="true",它将不会阻塞。但是目前只有几个浏览器支持这个功能,所以这对一般情况还没有帮助。

无论哪种方式,总的来说,将您的脚本标记放在页面的底部是一个好主意,这样它们就不会占用页面的其他部分。

默认情况下,Javascript 资产会阻止任何其他并行下载的发生。所以,你可以想象如果你的头部有大量的 <script>标签,调用多个外部脚本将阻止 HTML加载,因此用一个空白屏幕向用户问好,因为没有其他内容在你的页面将加载 直到的 JS 文件已经完全加载。

为了解决这个问题,许多开发人员选择将 JS 放在 HTML 页面的底部(在 </body>标记之前)。这似乎是合乎逻辑的,因为在大多数情况下,直到用户开始与站点进行交互,才需要 JS。将 JS 文件放在底部也可以实现渐进呈现。

或者,您可以选择异步加载 Javascript 文件。有许多现有的方法可以通过以下途径实现这一点:

XHR Eval

var xhrObj = getXHRObject();
xhrObj.onreadystatechange =
function() {
if ( xhrObj.readyState != 4 ) return;
eval(xhrObj.responseText);
};
xhrObj.open('GET', 'A.js', true);
xhrObj.send('');

脚本 DOM 元素

var se = document.createElement('script');
se.src = 'http://anydomain.com/A.js';
document.getElementsByTagName('head')
[0].appendChild(se);

Meebo 我陷害了 JS

var iframe = document.createElement('iframe');
document.body.appendChild(iframe);
var doc = iframe.contentWindow.document;
doc.open().write('<body onload="insertJS()">');
doc.close();

举几个例子。

注意 : 在当前浏览器中最多只能并行加载5个脚本。


对于 IE,可以像下面这样使用 defer属性:

<script defer src="jsasset.js" type="text/javascript"></script>

设置之后,这个布尔属性 向用户代理提示 脚本不会生成 任何文件内容(例如: 在 javascript 中使用“ document.write”)和 因此,用户代理可以继续 解析和渲染。

更新2022: 所有浏览器现在都接受 defer属性。

是的,它确实会影响网页的性能。

JavaScript 的问题在于阻塞了页面其余部分的执行/加载。如果你的 JavaScript 中有一些东西需要很长的时间,那么它会阻止页面的其余部分加载:

看看这些例子:

您可以看到警报对页面其余部分呈现的影响。放在页面顶部的任何 JavaScript 都会有同样的效果。一般来说,最好把任何关键的东西放在页面布局上(例如菜单插件或其他东西)。任何需要用户交互(弹出处理程序)或根本不涉及用户(Google Analytics)的内容都应该放在页面的底部。

您可以得到将 script标记注入到代码中的惰性加载程序。由于代码不在 HTML 中,因此可以确保整个页面呈现正确,并且包含的 JS 不会阻塞任何内容。

首先,没有包含在 body/head 元素中的 script 标签会创建无效的 HTML,甚至可能在某些浏览器中导致一些异常。

Head 元素中的脚本标记将在呈现任何 HTML 之前加载和解释,这将阻止 HTML/CSS 呈现。

脚本标签在 body 标签的底部,不会阻止 HTML/CSS,而且因为你只能在 DomReady 上使用 DOM,所以这是放置 JavaScript 的最佳位置。另外,您甚至不需要使用 domReady 事件包装器。

或者,您也可以使用类似 实验室需要的库从 head 标记启动 JavaScript (最小的 HTML/CSS 阻塞)。通过这两个库中的任何一个加载的任何脚本都将与 HTML/CSS 呈现并行运行。

<head>
<script data-main="INITSCRIPT.js" src="require.js"></script>
</head>

INITSCRIPT.js

require( [ "jQuery" , "somePlugin" ] , function(){
$(document).ready(function(){
$("#someId").somePlugin();
});
} );

在上面的示例中,只有 Reque.js 的加载和解释将阻止 HTML/CSS 呈现,这通常是不重要的。之后,jQuery 和 somPlugin 将被并行加载,这样 HTML/CSS 就可以很好地呈现了。

因此,我知道这是一个老的讨论,但我一直在阅读关于这个主题和其他答案的 StackOverflow..。

实际上,jQuery 标签放在哪里已经不重要了:

最后,一个词关于持续的民间传说。你可能会遇到 经常重复的建议是“始终将 JavaScript 放在 在页面的底部,就在结束标签之前”。这是一次 因为浏览器按顺序加载脚本并阻塞 加载和呈现,直到每个脚本完成 现代浏览器会“预加载扫描”并开始加载 所有并行的脚本,无论是在 head 元素中还是在 外部 JavaScript 通常是异步加载的 并且它被写入,所以直到加载页和 DOM 已经准备好了。在 head 元素中加载脚本不再是一件坏事 练习。

Http://railsapps.github.io/rails-javascript-include-external.html

除了性能方面之外,无论何时在 <head>标记中包含 <script>标记,都需要小心。

让我们考虑下面的例子:

<head>
<script>document.getElementById("demo").innerHTML="hello";</script>
</head>
<body>
<p id="demo">The content of the document......</p>
</body>

在这里,请注意脚本是在加载 DOM (或 <p>标记)之前加载的,这会导致脚本失败(因为 getElementById 无法找到名为“ demo”的元素)。

在这种情况下,只能在 body 标记中使用脚本。

考虑到其他答案,最好在 </body>标记之前放置脚本,因为您永远不知道外部加载的脚本是否与 DOM 有任何这样的依赖关系。

参考资料: 详细的问题描述