我应该在哪里将<script>标记放在HTML标记中?</script>

时间:2009-01-12 18:15:55

标签: javascript jquery html

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

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

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

24 个答案:

答案 0 :(得分:1669)

以下是当浏览器加载带有<script>标记的网站时会发生什么:

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

    因为您的浏览器不知道我的脚本。在下载文件之前,我不会修改文件。执行后,解析器停止解析。

    过时的推荐

    解决此问题的旧方法是将<script>标记放在<body>的底部,因为这样可以确保解析器不会被阻塞直到最后。

    这种方法有其自身的问题:在解析整个文档之前,浏览器无法开始下载脚本。适用于大型脚本和大型网站的大型网站样式表,能够尽快下载脚本对性能非常重要。如果您的网站在2秒内没有加载,人们将转到另一个网站。

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

    现代方法

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

    异步

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

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

    根据http://caniuse.com/#feat=script-async,94.57%的浏览器都支持此功能。

    延迟

    <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,94.59%的浏览器支持此功能。 94.92%至少部分支持它。

    关于浏览器兼容性的重要说明:在某些情况下,IE&lt; = 9可能无序地执行延迟脚本。如果您需要支持这些浏览器,请先阅读this

    结论

    目前最先进的技术是将脚本放在<head>标记中,并使用asyncdefer属性。这样可以在不阻止浏览器的情况下尽快下载脚本。

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

答案 1 :(得分:227)

就在关闭身体标签之前,如

所述

http://developer.yahoo.com/performance/rules.html#js_bottom

  

将脚本放在底部

     

脚本引起的问题是它们会阻止并行下载。 HTTP / 1.1规范建议浏览器每个主机名并行下载不超过两个组件。如果您从多个主机名提供图像,则可以并行执行两次以上的下载。但是,在下载脚本时,即使在不同的主机名上,浏览器也不会启动任何其他下载。

答案 2 :(得分:66)

非阻塞脚本标记几乎可以放在任何地方:

<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现在支持非阻塞执行。以下是loading the Google Maps API asynchronously的示例。

答案 3 :(得分:36)

雅虎推出的标准建议!卓越的性能团队,是将<script>标记放在文档正文的末尾,这样它们就不会阻止页面的呈现。

但有一些较新的方法可以提供更好的效果,如this answer中所述,关于Google AnalyticsJavaScript文件的加载时间:

  

Steve Souders(客户端性能专家)有一些great slides关于:

     
      
  • 并行加载外部JavaScript文件的不同技术
  •   
  • 它们对加载时间和页面呈现的影响
  •   
  • 浏览器显示哪种“进行中”指示符(例如,状态栏中的“加载”,沙漏鼠标光标)。
  •   

答案 4 :(得分:23)

如果您正在使用JQuery,那么将javascript置于最佳位置,并使用$(document).ready()确保在执行任何功能之前正确加载内容。

旁注:我喜欢<head>部分中的所有脚本标签,因为这似乎是最干净的地方。

答案 5 :(得分:10)

XHTML不会验证脚本是否在head元素之外的任何位置。结果表明它可以在任何地方。

你可以用jQuery之类的命令推迟执行,所以它放在哪里并不重要(解析过程中的性能损失很小)。

答案 6 :(得分:9)

<script src="myjs.js"></script>
</body>

脚本标记应始终在正文关闭底部在HTML 文件之前使用。

然后您可以在加载 js 文件之前先查看页面内容。

如果需要,检查一下: http://stevesouders.com/hpws/rule-js-bottom.php

答案 7 :(得分:6)

传统(并且被广泛接受)的答案是“在底部”,因为在任何事情开始执行之前,整个DOM都会被加载。

出于各种原因,有异议者从可用的练习开始,故意开始执行页面onload事件。

答案 8 :(得分:3)

2019年的现代方法是使用ES6模块类型脚本

<script type="module" src="..."></script>

默认情况下,模块被异步加载并延迟。即您可以将它们放置在任何地方,它们将并行加载并在页面加载完成后执行。

脚本和模块之间的区别在这里描述:

https://stackoverflow.com/a/53821485/731548

与脚本相比,模块的执行描述如下:

https://developers.google.com/web/fundamentals/primers/modules#defer

此处显示了支持:

https://caniuse.com/#feat=es6-module

答案 9 :(得分:2)

根据脚本及其用法,尽可能最好(在页面加载和呈现时间方面)可能不使用传统的&lt; script&gt; -tag本身,而是动态地异步加载脚本。

有一些不同的技术,但最直接的是在触发window.onload事件时使用document.createElement(“script”)。然后在页面本身渲染时首先加载脚本,这样就不会影响用户等待页面显示的时间。

这自然要求渲染页面不需要脚本本身。

有关详细信息,请参阅Steve Souders的帖子Coupling async scripts(YSlow的创建者,但现在在Google上)。

答案 10 :(得分:1)

  • 如果您仍然非常关心IE&lt; 10中的支持和性能,那么最好始终将脚本标记为HTML正文的最后一个标记。这样,您就可以确定已经加载了其余的DOM,并且您不会阻止和渲染。

  • 如果你对IE&lt; 10不再太在意了,你可能想把你的脚本放在文档的头部并使用defer来确保它们只在你的DOM之后运行已加载(<script type="text/javascript" src="path/to/script1.js" defer></script>)。如果您仍希望您的代码在IE&lt; 10中工作,请不要忘记将代码包装在window.onload中,但是!

答案 11 :(得分:1)

您可以通过使用封装 JavaScript 代码的专用 HTML 标记 <script> 在 HTML 文档中添加 JavaScript 代码。

<script> 标记可以放置在 HTML 的 <head> 部分、<body> 部分或 </body> 结束标记之后,具体取决于您何时需要要加载的 JavaScript。

通常,JavaScript 代码可以放在文档 <head> 部分的内部,以便将它们包含在 HTML 文档的主要内容之外。

但是,如果您的脚本需要在页面布局内的某个点运行——比如使用 document.write 生成内容时——您应该将它放在应该调用它的位置,通常在 {{ 1}} 部分。

答案 12 :(得分:1)

最后包含脚本主要用于首先显示网站内容/样式的地方。

包括头部的脚本,可以尽早加载脚本,并可以在加载整个网站之前使用。

如果最后输入脚本,则只有在加载完整的样式和设计之后才会进行验证,这对于快速响应的网站是不受欢迎的。

答案 13 :(得分:1)

您可以将大多数<script>引用置于<body>的末尾,但如果您的网页上有活动组件正在使用外部脚本, 然后他们的依赖(js文件)应该在那之前(理想情况下在head标签中)。

答案 14 :(得分:1)

我认为这取决于网页的执行情况。如果您要显示的页面在未先加载JavaScript的情况下无法正常显示,则应首先包含JavaScript文件。但是如果您可以在不首先下载JavaScript文件的情况下显示/呈现网页,那么您应该将JavaScript代码放在页面底部。因为它会模拟快速的页面加载,并且从用户的角度来看,似乎该页面的加载速度更快。

答案 15 :(得分:1)

脚本阻止DOM加载,直到加载并执行。

如果您将脚本放在<body>的末尾,则所有DOM都有机会加载和渲染(页面将&#34;显示&#34;更快)。 <script>可以访问所有这些DOM元素。

另一方面,在<body>开始或之后放置它将执行脚本(其中仍然没有DOM元素)。

您正在使用jQuery,这意味着您可以将其放在任何地方,并使用.ready()

答案 16 :(得分:1)

取决于,如果您要加载一个脚本,这个脚本需要设置页面样式/使用页面中的操作(例如单击按钮),那么最好将其置于顶部。如果您的样式是100%CSS并且您拥有按钮操作的所有后备选项,那么您可以将它放在底部。

或者最好的事情(如果这不是一个问题)你可以制作一个模态加载框,将你的javascript放在你的页面底部,并在你的脚本的最后一行加载时使它消失。这样,您可以避免用户在加载脚本之前在页面中使用操作。并且还要避免不正确的造型。

答案 17 :(得分:0)

在HTML文档的末尾

因此,它不会影响执行时在浏览器中加载HTML文档。

答案 18 :(得分:0)

放置<script>标记的最佳位置是在关闭</body>标记之前,因此,下载并执行该标记不会阻止浏览器解析文档中的html,

从外部加载js文件也有其自身的优势,例如它将被浏览器缓存并可以加快页面加载时间分离HTML和JavaScript代码,并帮助更好地管理代码库

但是现代浏览器还支持其他一些最佳方式,例如asyncdefer来加载外部javascript文件。

异步和延迟

通常,HTML页面的执行逐行开始。当遇到外部JavaScript元素时,HTML解析将停止,直到下载JavaScript并准备执行为止。可以使用deferasync属性来更改此常规页面执行。

Defer

使用defer属性时,JavaScript与HTML解析并行下载,但是只有在完整的HTML解析完成后才能执行。

<script src="/local-js-path/myScript.js" defer></script>

Async

使用async属性时,JavaScript会在遇到脚本后立即下载,下载后,它将与HTML解析一起异步(并行)执行。

<script src="/local-js-path/myScript.js" async></script>

何时使用哪些属性

  • 如果您的脚本独立于其他脚本并且是模块化的,请使用     async
  • 如果您使用async加载script1和script2,则两者都将运行
    下载后,它们与HTML解析并行进行
    并可用。
  • 如果您的脚本依赖于另一个脚本,请同时使用defer
  • defer依次加载script1和script2时, 一定要先执行script1,
  • 然后script2将在完全执行script1之后执行。
  • 如果script2依赖于script1,则必须执行此操作。
  • 如果您的脚本足够小并且受另一个脚本的依赖 类型async的脚本,然后使用没有属性的脚本并将其放置 高于所有async脚本。

参考:knowledgehills.com

答案 19 :(得分:0)

在body标记结束之前,以防止和UI阻塞。

答案 20 :(得分:-1)

在HTML之后包含脚本对我来说更有意义。因为大多数时候我需要在执行脚本之前加载Dom。我可以将它放在head标签中,但我不喜欢所有Document加载监听器开销。我希望我的代码简短,甜美,易于阅读。

我听说在head标签之外添加你的脚本时,旧版本的safari很夸张,但我说谁在乎。我不知道有人使用那个旧垃圾吗。

顺便说一句好问题。

答案 21 :(得分:-1)

JavaScript 脚本:

常规 VS。异步 VS。推迟

enter image description here

enter image description here

答案 22 :(得分:-2)

在标记加载文档然后执行js代码之后,在文档代码末尾编写JavaScript代码的最佳位置。 如果你写JQuery代码写

$(document).ready(function(){

//your code here...

});

答案 23 :(得分:-5)

您可以将脚本放置在您想要的位置,而不是另一种习惯。

情况如下:

页面线性加载,“自上而下”,所以如果你把脚本放在头部确保它开始加载之前的一切,现在,如果你把它放在体内与代码混合可能会导致页面加载难看的方式。

确定良好做法并不取决于何处。

为了支持你,我将提到以下内容:

你可以放置:

,页面将线性加载

页面与其他内容

异步加载

页面内容将在加载脚本加载完成之前和之后加载

这里的良好做法是,何时实施?

我希望我一直很有帮助,只要回答我这个问题。