【问题标题】:Is it necessary to put scripts at the bottom of a page when using the "defer" attribute?使用“defer”属性时是否需要将脚本放在页面底部?
【发布时间】:2012-09-07 03:12:54
【问题描述】:

我总是将脚本标签放在页面底部,因为在 HTML/CSS 和文本等内容完成加载后加载脚本是一种很好的做法。我刚刚发现了 defer 属性,它基本上做同样的事情,即它等到页面完成加载,然后再获取和执行脚本。

那么如果使用 defer 属性,是否有必要将 script 标签物理放置在页面底部而不是 head 标签内?

我发现将脚本标签保留在 head 部分中会更好地提高可读性。

<script src="script.js" defer="defer"></script>

<script defer="defer">

// do something

</script>

【问题讨论】:

  • 您的第二个示例实际上不会被推迟。 defer 仅适用于外部脚本。
  • 不会把脚本放在末尾 将其设置为延迟是多余的吗?至于到底要不要用defer,难道要忽略Opera的市场份额吗? (显然 Opera 也不支持 html5 async 属性。)您可能需要考虑类似 yepnope.js 的东西。
  • 推论是,如果您需要使用一些文字脚本,那么延迟的外部脚本和文字脚本的执行顺序将突然变得非常重要,以便在读取 HTML 源时确定。你需要做的是确保所有脚本(除了 Modernizr 和其他应该提前加载的脚本)都是从外部文件加载的,并将它们声明为延迟。与确保脚本包含在文件末尾相比,这似乎并没有那么麻烦。当然它更干净,但是为什么有人会选择其他选项是可以理解的。
  • @millimoose 实际上,它在 Gecko 1.9.1 中也适用于内部脚本-
  • 从本质上讲,我的观点是,如果您将未延迟的脚本保留在页面底部,您就知道它们何时执行,您知道它们将按什么顺序执行,并且您知道什么这将对性能产生影响。如果您在 &lt;head&gt; 中使用延迟脚本,则您依赖于特定浏览器的实现细节/对 HTML5 的遵守。

标签: javascript html


【解决方案1】:

当前的最佳实践? 在头部按顺序使用延迟脚本,除非您需要支持较旧的浏览器(IE ref)

为什么? 使用defer,解析就像我们将脚本放在body标签末尾一样完成,但总体而言,脚本执行之前完成得很好,因为脚本已经下载到与 HTML 解析并行。此方案将触发更快的domInteractive 事件,该事件用于页面加载速度。使用async,脚本的执行顺序会根据获取脚本的速度而有所不同,因此可能会影响顺序。此外,async 脚本内联执行并暂停 HTML 解析。

【讨论】:

  • 浏览器已经可以并且将呈现部分加载的 HTML,即使没有关于特定元素是否会生成内容的提示。换句话说,如果你在结束 &lt;/html&gt; 之前添加一个&lt;script&gt;,我相信大多数浏览器会在下载外部脚本之前/同时呈现他们迄今为止遇到的 HTML。
  • 对于一个愚蠢的例子,请参阅:dl.dropbox.com/u/263227/test.html。在alert() 执行之前,页面已完成渲染。仅仅存在未延迟的&lt;script&gt;,即使是使用document.write() 的,也不会阻止浏览器呈现它目前看到的页面。虽然使用defer可能有性能优势,但我真的怀疑是否存在显着的优势。
  • @millimoose 谢谢你的例子,我相信我们都不想等待
  • @mac9416 这个答案写于 2012 年,显然没有得到维护。我会继续更新我的答案以保持相关性。
  • @BenSewards 刚刚注意到这仍然关闭:“使用此替代属性表示脚本不包含 document.write”。这仅适用于async。延迟脚本可以绝对使用document.write,因为它们会在DOM 的其余部分加载后同步并按顺序执行。 async 脚本应该使用document.write,因为无法预测写入发生的位置。
【解决方案2】:

自编写这些答案以来,最佳实践发生了变化,因为对 defer 属性的支持已发展到 98% globally

除非您需要针对旧版浏览器优化速度,否则您应该将脚本放在头部并标记为延迟。这 1) 将所有脚本引用保存在一个位置(更易于维护)和 2) 使浏览器更快地了解脚本,从而使其更早地开始优先考虑资源。

对于大多数页面来说,性能差异应该可以忽略不计,因为浏览器的pre-loader 可能在整个文档被解析之前不会开始下载延迟脚本。但是,它不应该受到伤害,而且它为浏览器留下了更多的工作,这通常是最好的。

【讨论】:

  • 现在是 97% :P
【解决方案3】:

首先,并非所有浏览器都支持 defer 属性(有些支持它的只是忽略它)。将脚本放在页面底部可确保其上方的所有 HTML 元素在脚本执行之前都已加载到 DOM 中。另一种方法是使用onload 方法或使用jQuery 的DOM ready 函数。

【讨论】:

  • 我相信 Onload 和 domready 是不同的。 Onload 将在页面上的所有内容完全加载完成后触发,而 domready 会在 dom 准备好被操作时触发,即使某些内容尚未完成加载。
  • onload/ready 不是替代方案,因为它仍然需要在继续页面之前加载脚本。
  • 自 2/2015 起,除 Opera Mini 之外的所有浏览器、桌面和移动设备都支持 defer。请开始使用它。
【解决方案4】:

在 HTML 底部的脚本中使用 defer 有不同的原因:

  • 并非所有浏览器都支持“延迟”。如果您将脚本放在带有 defer 的 HEAD 中并且浏览器不支持 defer,则该脚本会阻止以下元素的并行下载,并且还会阻止脚本下方所有内容的渐进式渲染。
  • 如果您只是将脚本放在底部而不延迟,浏览器将继续显示繁忙指示符,直到页面完成 JavaScript 解析。
  • 在某些情况下,“底部没有延迟的脚本”会阻止渐进式渲染。在 Google Chrome 36 和 IE11 中测试(见下方评论)

重要的是要知道每个浏览器都处理“延迟”之类的事情,而且繁忙的指标也略有不同。

最佳实践应该是:使用 defer 将脚本放在底部。

除了可读性方面,与“带延迟的头中脚本”或“不带延迟的底部脚本”相比,我只看到将脚本放在底部并带有延迟的优势。

【讨论】:

  • 这里你也可以看到谷歌浏览器中“没有延迟的底部脚本”和“有延迟的底部脚本”之间的明显区别。在这个测试中,“没有延迟的底部脚本”阻止了特定点的渐进式渲染。 webpagetest.org/video/…
  • 根据 W3C,脚本可以进入正文,但在语义上它们属于头部。 #soapBox #nitPicking
  • @BITS - 你的链接失效了
【解决方案5】:

虽然我同意您的观点,即使用“延迟”并将脚本放在标题中会提高可读性,但桌面和移动 Opera 仍然不支持此属性(请查看 this table 了解详细信息)。

【讨论】:

  • 现在完全支持 Opera 桌面。安全使用,除了您的移动 Opera 用户(他们都是)。
猜你喜欢
  • 2017-02-12
  • 1970-01-01
  • 2020-10-03
  • 2021-02-07
  • 2014-04-21
  • 2022-07-07
  • 2011-10-16
  • 2016-03-30
  • 2010-09-27
相关资源
最近更新 更多