一尘不染

我应该将 <script> 标签放在 HTML 标记中的什么位置?

html

在 HTML 文档中嵌入 JavaScript 时,放置<script>标签和包含 JavaScript 的合适位置在哪里?我似乎记得您不应该将它们放在该<head>部分中,但是放置在该部分的开头也<body>很糟糕,因为必须在页面完全呈现之前解析 JavaScript(或类似的东西)。这似乎使该部分的末尾成为标签<body>的逻辑位置。<script>

那么,放置标签的正确位置在哪里?<script>


阅读 304

收藏
2022-02-17

共1个答案

一尘不染

当浏览器加载带有<script>标签的网站时,会发生以下情况:

  1. 获取 HTML 页面(例如index.html
  2. 开始解析 HTML
  3. 解析器遇到<script>引用外部脚本文件的标记。
  4. 浏览器请求脚本文件。同时,解析器会阻止并停止解析页面上的其他 HTML。
  5. 一段时间后,脚本被下载并随后执行。
  6. 解析器继续解析 HTML 文档的其余部分。

第 4 步会导致糟糕的用户体验。在您下载所有脚本之前,您的网站基本上会停止加载。如果用户讨厌一件事,那就是等待网站加载。

为什么会发生这种情况?

document.write()任何脚本都可以通过或其他 DOM 操作插入自己的 HTML 。这意味着解析器必须等到脚本下载并执行后才能安全地解析文档的其余部分。毕竟,脚本可以在文档中插入自己的 HTML。

但是,大多数 JavaScript 开发人员不再在文档加载时操作DOM。相反,他们会等到文档加载完毕后再进行修改。例如:

<!-- 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 秒内未加载,人们将转到另一个网站。

在最佳解决方案中,浏览器会尽快开始下载您的脚本,同时解析文档的其余部分。

现代方法

今天,浏览器支持脚本的asyncdefer属性。这些属性告诉浏览器在下载脚本时继续解析是安全的。

异步

<script src="path/to/script1.js" async></script>
<script src="path/to/script2.js" async></script>

具有 async 属性的脚本是异步执行的。这意味着脚本在下载后立即执行,同时不会阻止浏览器。这意味着脚本 2 可能在脚本 1 之前下载并执行。

根据http://caniuse.com/#feat=script-async,97.78% 的浏览器都支持这一点。

推迟

<script src="path/to/script1.js" defer></script>
<script src="path/to/script2.js" defer></script>

具有 defer 属性的脚本按顺序执行(即首先执行脚本 1,然后执行脚本 2)。这也不会阻止浏览器。

与异步脚本不同,延迟脚本仅在加载整个文档后执行。

根据http://caniuse.com/#feat=script-defer,97.79% 的浏览器都支持这一点。98.06% 至少部分支持它。

关于浏览器兼容性的重要说明:在某些情况下,Internet Explorer 9 和更早版本可能会乱序执行延迟脚本。如果您需要支持这些浏览器,请先阅读内容!

(要了解更多信息并查看异步、延迟和普通脚本之间差异的一些非常有用的视觉表示,请查看此答案参考部分的前两个链接)

结论

当前的最新技术是将脚本放在<head>标签中并使用asyncordefer属性。这允许您的脚本尽快下载,而不会阻止您的浏览器。

好消息是您的网站仍应在 2% 的不支持这些属性的浏览器上正确加载,同时加快其他 98% 的速度。

2022-02-17