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

标签 javascript jquery html

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

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

(这个问题引用了 this question ,其中建议 JavaScript 函数调用应该从 <a> 标签移动到 <script> 标签。我专门使用 jQuery,但更一般的答案也是合适的。)

最佳答案

以下是浏览器加载带有 <script> 的网站时发生的情况在上面标记:

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

  • 第 4 步会导致糟糕的用户体验。在您下载所有脚本之前,您的网站基本上会停止加载。如果用户讨厌一件事,那就是等待网站加载。
    为什么会发生这种情况?
    任何脚本都可以通过 document.write() 插入自己的 HTML或其他 DOM 操作。这意味着解析器必须等到脚本下载并执行后才能安全地解析文档的其余部分。毕竟,脚本可以在文档中插入自己的 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 属性的脚本是异步执行的。这意味着脚本在下载后立即执行,同时不会阻止浏览器。
    这意味着可以在脚本 1 之前下载和执行脚本 2。
    根据 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% 至少部分支持它。
    关于浏览器兼容性的一个重要说明:在某些情况下 IE <= 9 可能会乱序执行延迟脚本。如果您需要支持这些浏览器,请阅读 this第一的!
    (要了解更多信息并查看异步、延迟和普通脚本之间差异的一些非常有用的视觉表示,请查看此答案引用部分的前 2 个链接)
    结论
    当前最先进的技术是将脚本放入 <head>标记并使用 asyncdefer属性。这允许您的脚本尽快下载而不会阻止您的浏览器。
    好消息是,您的网站仍应在 2% 不支持这些属性的浏览器上正确加载,同时加快其他 98% 的速度。
    引用
  • async vs defer attributes
  • Efficiently load JavaScript with defer and async
  • Remove Render-Blocking JavaScript
  • Async, Defer, Modules: A Visual Cheatsheet
  • 关于javascript - 我应该将 &lt;script&gt; 标签放在 HTML 标记中的什么位置?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/436411/

    相关文章:

    php - 无法在脚本函数中传递 php 变量

    javascript - 变量返回未定义的Javascript

    html - 如何使滚动 div 高度仅与行中的同级 div 一样大

    javascript - 将鼠标悬停在图像上时如何输出按钮和文本?我需要使用 JQuery 吗?

    javascript - DOM 元素鼠标悬停时显示框? (带有可变数据)jQuery UI?

    javascript - 内联 Javascript 未在 IE11 上加载

    javascript - 无法与 javascript 中的 php echo 输出进行比较(jquery-post)

    javascript - 如何获取d3.select的父节点

    javascript - html mustache js 内的模板

    javascript - 我的颜色应用程序的 jQuery 更好的方式?