我应该在HTML标记中放置<script>标记?
将JavaScript嵌入到HTML文档中时,放置<script>
标记和包含JavaScript的适当位置在哪里? 我似乎还记得,你不应该把它们放在<head>
部分,但是放在<body>
部分的开头也是不好的,因为在页面完全呈现之前必须解析JavaScript(或类似的东西)。 这似乎将<body>
部分的末尾作为<script>
标记的逻辑位置。
那么,放置<script>
标签的正确位置在哪里?
(这个问题引用了这个问题,其中有人建议JavaScript函数调用应该从<a>
标记移动到<script>
标记。我特别使用jQuery,但更通用的答案也是适当的。)
以下是当浏览器加载带有<script>
标签的网站时发生的情况:
<script>
标签。 第4步导致不良的用户体验。 您的网站基本上停止加载,直到您下载所有脚本。 如果有一件事让用户讨厌它正在等待网站加载。
为什么这会发生?
任何脚本都可以通过document.write()
或其他DOM操作插入自己的HTML。 这意味着解析器必须等到脚本被下载并执行之后才能安全地解析文档的其余部分。 毕竟,该脚本可能已经在文档中插入了自己的HTML。
但是,大多数JavaScript开发人员在文档加载时不再操作DOM。 相反,他们会等到文档被加载后再修改它。 例如:
<!-- index.html -->
<html>
<head>
<title>My Page</title>
<script type="text/javascript" src="my-script.js"></script>
</head>
<body>
<div id="user-greeting">Welcome back, user</div>
</body>
</html>
使用Javascript:
// my-script.js
document.addEventListener("DOMContentLoaded", function() {
// this function runs when the DOM is ready, i.e. when the document has been parsed
document.getElementById("user-greeting").textContent = "Welcome back, Bart";
});
因为你的浏览器不知道my-script.js在下载并执行之前不会修改文档,解析器会停止解析。
陈旧的建议
解决此问题的旧方法是将<script>
标记放在<body>
的底部,因为这可确保解析器在最后才会被阻止。
这种方法有其自身的问题:在整个文档被解析之前,浏览器不能开始下载脚本。 对于大型脚本和样式表的大型网站,能够尽快下载脚本对性能非常重要。 如果您的网站在2秒内未加载,用户将转到其他网站。
在最佳解决方案中,浏览器将尽快下载脚本,同时解析文档的其余部分。
现代的方法
今天,浏览器支持脚本的async
和defer
属性。 这些属性告诉浏览器在下载脚本时继续解析是安全的。
异步
<script type="text/javascript" src="path/to/script1.js" async></script>
<script type="text/javascript" src="path/to/script2.js" async></script>
具有异步属性的脚本异步执行。 这意味着脚本在下载后立即执行,同时不会阻止浏览器。
这意味着脚本2可以在脚本1之前下载并执行。
根据http://caniuse.com/#feat=script-async,90%的浏览器都支持这一点。
延缓
<script type="text/javascript" src="path/to/script1.js" defer></script>
<script type="text/javascript" src="path/to/script2.js" defer></script>
具有defer属性的脚本按顺序执行(即第一个脚本1,然后是脚本2)。 这也不会阻止浏览器。
与异步脚本不同,延迟脚本仅在整个文档被加载后执行。
根据http://caniuse.com/#feat=script-defer,所有浏览器的90%都支持这一点。 92%至少部分支持它。
关于浏览器兼容性的一个重要注意事项:在某些情况下,IE <= 9可能会按顺序执行延迟脚本。 如果您需要支持这些浏览器,请先阅读本文!
结论
目前最先进的技术是将脚本放在<head>
标签中,并使用async
或defer
属性。 这可以让您的脚本尽快下载,而不会阻塞您的浏览器。
好处是你的网站仍然应该在不支持这些属性的20%的浏览器上正确加载,而加速其他80%。
正如前面所述,在结束标签之前
http://developer.yahoo.com/performance/rules.html#js_bottom
将脚本放在底部
脚本导致的问题是它们会阻止并行下载。 HTTP / 1.1规范建议浏览器每个主机名并行下载至少两个组件。 如果您从多个主机名提供图像,则可以同时发生两个以上的下载。 然而,当脚本正在下载时,浏览器将不会启动任何其他下载,即使是在不同的主机名上。
非阻塞脚本标签可以放在任何地方:
<script src="script.js" async></script>
<script src="script.js" defer></script>
<script src="script.js" async defer></script>
async
脚本将在可用时立即执行 defer
脚本被执行 async defer
脚本会回退到延迟行为 这些脚本将在文档准备好后异步执行,这意味着您不能这样做:
<script src="jquery.js" async></script>
<script>jQuery(something);</script>
<!--
* might throw "jQuery is not defined" error
* defer will not work either
-->
或这个:
<script src="document.write(something).js" async></script>
<!--
* might issue "cannot write into document from an asynchronous script" warning
* defer will not work either
-->
或这个:
<script src="jquery.js" async></script>
<script src="jQuery(something).js" async></script>
<!--
* might throw "jQuery is not defined" error (no guarantee which script runs first)
* defer will work in sane browsers
-->
或这个:
<script src="document.getElementById(header).js" async></script>
<div id="header"></div>
<!--
* might not locate #header (script could fire before parser looks at the next line)
* defer will work in sane browsers
-->
话虽如此,异步脚本提供了这些优点:
浏览器可以并行下载样式表,图像和其他脚本,无需等待脚本下载和执行。
您可以将脚本放置在头部或身体中,而无需担心阻塞(如果使用CMS,则可用)。 执行顺序依然很重要。
通过使用支持回调的外部脚本可以规避执行顺序问题。 许多第三方JavaScript API现在支持非阻塞执行。 以下是异步加载Google Maps API的示例。
链接地址: http://www.djcxy.com/p/12371.html上一篇: Where should I put <script> tags in HTML markup?
下一篇: How can you check for a #hash in a URL using JavaScript?