我应该将脚本标签放在 HTML 文档中的什么位置?
最好的方法是将 JavaScript<script>
标记放在结束</body>
标记之前,而不是放在<head>
HTML 部分中。原因是 HTML 从上到下加载。头部首先加载,然后是身体,然后是身体内的所有东西。
当浏览器加载带有<script>
标签的网站时,会发生以下情况:
- 获取 HTML 页面(例如
index.html
) - 开始解析 HTML
- 解析器遇到
<script>
引用外部脚本文件的标记。 - 浏览器请求脚本文件。同时,解析器会阻止并停止解析页面上的其他 HTML。
- 一段时间后,脚本被下载并随后执行。
- 解析器继续解析 HTML 文档的其余部分。
第 4 步解析器停止页面HTML的解析会 导致糟糕的用户体验。在下载所有脚本之前,网站基本上会停止加载。用户需要长时间的等待网站加载。
为什么会发生这种情况?
document.write()
可以通过 DOM 操作插入自己的 HTML 。这意味着解析器必须等到脚本下载并执行后才能安全地解析文档的其余部分。毕竟,脚本可以在文档中插入自己的 HTML。
但是,大多数 JavaScript 开发人员不会在文档加载时操作 DOM。相反,他们会等到文档加载完毕后再进行修改。例如:
HTML
<!-- index.html -->
<html>
<head>
<title>My Page</title>
<script 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
属性。这些属性告诉浏览器在下载脚本时继续解析是安全的。
async异步:
<script src="path/to/script1.js" async></script>
<script src="path/to/script2.js" async></script>
async
具有该属性的脚本是异步执行的。这意味着脚本在下载后立即执行,同时不会阻塞浏览器。这意味着脚本 2 可能在脚本 1 之前下载并执行。
defer推迟:
<script src="path/to/script1.js" defer></script>
<script src="path/to/script2.js" defer></script>
具有该defer
属性的脚本按顺序执行(即首先执行脚本 1,然后执行脚本 2)。这也不会阻止浏览器。
与async
脚本不同,defer
脚本仅在整个文档加载完成后才会执行。
关于浏览器兼容性的重要说明:在某些情况下,Internet Explorer 9 和更早版本可能会乱序执行延迟脚本。
结论
当前的最新技术是将脚本放在<head>
标签中并使用async
ordefer
属性。这允许脚本尽快下载,而不会阻止浏览器解析html。
- 点赞
- 收藏
- 关注作者
评论(0)