【问题标题】:Defer Attribute (Chrome)延迟属性 (Chrome)
【发布时间】:2011-04-26 12:07:34
【问题描述】:

Chrome 对我来说一直是 web 标准的参考,不幸的是 defer 不受支持,IE 从 5.5 版开始支持它。为什么?

js.js

document.getElementById ("hi").innerHTML = "Hi :)";

HTML

<!DOCTYPE html>
<html>
    <head>
        <meta charset = "utf-8">
        <script defer="defer" src="js.js"></script>
        <title>Hi</title>
    </head>
    <body>
        <div id="hi"></div>
    </body>
</html>

【问题讨论】:

  • 虽然我不能告诉你为什么 chrome 不使用它,但我相信你可以使用“async”属性来产生类似的效果(如果我错了请纠正我......)
  • 或者你可以把样式放在页面顶部,把脚本放在底部,就像你应该做的那样。
  • @ChristianMann 你的意思是在页面底部吗?为什么要这么做?这是无效的标记
  • 您可以将脚本标签放在您想要的任何位置(在headbody 内)。当前的最佳实践建议是将所有脚本放在结束 &lt;/body&gt; 标记之前。

标签: javascript google-chrome attributes


【解决方案1】:

deferasync 是什么意思?

默认情况下,&lt;script src=...&gt;&lt;/script&gt; 标记是邪恶的! 浏览器必须停止解析 HTML,直到脚本被下载并执行(因为脚本可能会调用 document.write(...) 或定义稍后的全局变量脚本取决于)。这意味着脚本标签之后的任何图像和样式表在脚本完成下载和执行之前不会开始下载。外部脚本通常会使 Web 加载更慢,这就是 NoScript 如此受欢迎的原因。

微软引入defer 来解决这个问题。如果您使用&lt;script defer src=...&gt;&lt;/script&gt;,您承诺不致电document.write(...)defer 外部脚本将立即开始下载,但直到页面呈现后才会执行。页面呈现后,所有defer 脚本都按照它们声明的顺序执行。并非所有浏览器都实现defer

HTML5 引入了async 属性,它可以在任何时间执行——可能在页面完成解析之前,甚至在其他仍在下载的defer/async 脚本之前执行。但是使用多个async 脚本更加困难,因为它们的执行顺序无法保证。与defer 一样,并非所有浏览器都实现async

在所有 deferasync 脚本都已执行后,DOMContentLoadedload 事件将触发。

deferasync 的简史

  • 1997 IE 4 引入了defer
  • 1998 HTML 4 spec mentions defer,但不幸的是,它并没有准确说明 defer 脚本的执行时间(全部按顺序执行?在 onload 之前?)。因此,没有其他浏览器实现defer,因为没有人想对 IE 的行为进行逆向工程或破坏可能取决于 IE 特性的脚本。 (例如,请参阅Mozilla feature request)。
  • 2006 HTML5 草案最终描述了实现defer 所需的细节:defer 脚本都应在解析页面其余部分之后、onload 之前按顺序执行。它还引入了async 来指定可以在下载时执行的脚本,而无需相互等待。不幸的是,HTML5 与 IE 相矛盾,因为它不允许内联 defer 脚本。这打破了所有defer 脚本按顺序执行的不变量(如果某些defer 脚本具有src 并且有些具有内联内容)。
  • 2009 Gecko 1.9.1 (Firefox 3.5) supports defer.
  • 2010-01 Gecko 1.9.2 (Firefox 3.6) supports async.
  • 2010-09 defer and async are checked into Webkit。您应该很快就会在 Chrome 和 Safari 中看到它(它已经在 Chrome 开发者频道中,但有点问题)。
  • 我们仍在等待 Opera 实现 deferasync 以及 IE 实现 async

那么 Web 开发人员应该使用什么?

目前没有可遵循的单一规则。您必须为访问您网站的浏览器组选择最能平衡简单性、页面呈现延迟和脚本执行延迟的解决方案。

  • 正如其他人指出的那样,在脚本执行之前呈现页面的最简单方法是将脚本放在页面底部。但如果脚本是必不可少的,或者网页包含大量 HTML,那么您应该将脚本放在页面的较高位置。
  • 如果您的脚本是独立的并且您的客户使用 IE 或新版本的 Firefox,请使用 &lt;script async defer src=...&gt;&lt;/script&gt;:这允许渲染继续并行下载 IE 和最新 HTML5 浏览器的脚本,但会导致 HTML5 之前的浏览器(包括所有Opera 版本)来阻止。
  • 如果一个外部脚本依赖于另一个,请将它们都标记为defer(但不是async),它们将按照声明的顺序执行(IE<=9 in certain conditions can execute them out of order 除外)。同样,这允许渲染在 IE 和支持 HTML5 的 Gecko/Webkit 中与脚本下载并行继续进行,但较旧的浏览器和 Opera 会受到影响。使用defer 是个好主意,即使脚本位于页面底部,以便它们彼此并行下载。
  • 切勿将defer 用于内联脚本,因为HTML5 草案已经取消了执行顺序保证。
  • 如果您的受众包括许多 Opera 或旧 Firefox/Safari 用户,以下 sn-p 将在大多数 pre-HTML5 浏览器(IE、Webkit、需要测试旧 Firefox)上解析文档后执行脚本,而最新的支持 HTML5 的浏览器会立即开始下载,但不会因为 async 属性而阻止执行脚本。换句话说,大多数旧版浏览器将其视为页面底部的脚本,而最新版浏览器识别async。但是 Opera 用户得到了两全其美的结果,因为 Opera 立即开始执行并且不理解async。这是许多网页上的 urchin 的 pattern recommended by Google Analytics

sn-p:

<script>
(function() {
  var script = document.createElement('script');
  script.src = '...';
  script.async = true;
  var s = document.getElementsByTagName('script')[0];
  s.parentNode.insertBefore(script, s);
})();
</script>
  • 如果另一个脚本依赖于第一个脚本来加载,那么您可以使用与上述相同的模式,但在执行第二个脚本之前监听第一个脚本元素的 onload 事件。请参阅LABjs example for how to wait for another script to load
  • 如果您有多个具有复杂依赖关系的脚本,请使用LAB.jsYUI Loader 使它们并行下载并以某种有效的顺序执行。
  • 如果您使用的是 jQuery 等流行库,请考虑使用 Google's copy 而不是您自己的库,以增加浏览器已经缓存它的可能性。

更新:如果您将脚本拆分为模块并希望提高性能,我推荐 Steve Souder 的 Even Faster Web Sites 的“耦合异步脚本”一章。它包含的提示/技巧不仅可以控制执行顺序,还可以延迟脚本解析以提高性能。

【讨论】:

  • 我从这里得到了这个:“即使脚本位于页面底部,使用 defer 也是一个好主意,以便它们彼此并行下载。”重要的一个。
  • 注意这个问题:github.com/h5bp/lazyweb-requests/issues/42 TL;DR,defer 不保证 IE 中的顺序 defer,你可能还是有问题。
【解决方案2】:

defer 仅受 Internet Explorer 支持。你不需要依赖它。正如其他人指出的那样,还有其他方法可以获得相同的效果,例如将脚本放在页面末尾的 &lt;/body&gt; 标记之前。

defer 的目的是告诉 外部链接脚本等到 页面完成加载,直到它 运行。同样的事情可以 通过良好的不引人注目来完成 JavaScript 方法,通常 包含阻止脚本的代码 从执行到 DOM 加载完毕。

defer 的优势体现在 与 Internet Explorer 连接, 因为那个浏览器是唯一的 支持 defer 属性。所以, 如果您只需要一个快速脚本来运行 在 IE 中,你不介意如果 整个页面在开始之前加载 执行,然后简单地添加 defer="defer" 在您的标签中,这将 快速解决这个问题。 修复 IE6 中的透明 PNG 问题 是一种可能的实际用途 推迟。

defer 属性必须 隐藏脚本时使用 其他带有条件的浏览器 针对仅 IE 脚本的注释 — 否则脚本将运行 通常在其他浏览器中。)

参考:http://www.impressivewebs.com/10-javascript-quick-tips-and-best-practices/

【讨论】:

  • 只是一个旁注:firefox 3.5+ 也支持defer
【解决方案3】:

如果脚本可以延迟,它们也可以移动到页面底部(正如@Christian 在 cmets 中指出的那样)

就性能而言,这将是一个更好的选择,因为它不会阻止页面的其余部分加载。您可以将脚本放在&lt;/body&gt; 标记之前。

主要浏览器对该属性的支持很差,这本身应该是停止使用它的提示。

【讨论】:

  • 脚本元素永远不应该存储在 body 元素中...除非你想做出最小的努力,而不是致力于下一个很酷的事情,而是把所有的时间都花在维护糟糕的代码上.
猜你喜欢
  • 2017-12-28
  • 2013-07-03
  • 2014-07-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-08
  • 1970-01-01
相关资源
最近更新 更多