Javascript 延迟属性 (Chrome)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3952009/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Defer Attribute (Chrome)
提问by Caio
Chrome for me has always been a reference on web standards, unfortunately the deferisn't supported and IE supports it since version 5.5. Why ?
Chrome 对我来说一直是 Web 标准的参考,遗憾的是不支持defer,IE 从 5.5 版开始支持它。为什么 ?
js.js
js.js
document.getElementById ("hi").innerHTML = "Hi :)";
HTML
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>
回答by yonran
What do defer
and async
mean?
什么defer
和async
意味着什么呢?
By default, a <script src=...></script>
tag is evil!The browser must halt parsing the HTML until the script is downloaded and executed (since the script might call document.write(...)
or define global variables that later scripts depend on). This means that any images and stylesheets that are after the script tag don't start downloading until after the script has finished downloading and executing. External scripts typically make the Web load much more slowly, which is why NoScript has become so popular.
默认情况下,<script src=...></script>
标签是邪恶的!浏览器必须停止解析 HTML,直到下载并执行脚本(因为脚本可能会调用document.write(...)
或定义以后脚本所依赖的全局变量)。这意味着脚本标记之后的任何图像和样式表在脚本完成下载和执行之前不会开始下载。外部脚本通常会使 Web 加载更慢,这就是 NoScript 变得如此流行的原因。
Microsoft introduced defer
to solve the problem. If you use <script defer src=...></script>
, you promise not to call document.write(...)
. A defer
external script will start downloading immediately but won't execute until after the page is rendered. After the page has rendered, all defer
scripts are executed in the same order that they were declared. Not all browsers implement defer
yet.
微软推出defer
来解决这个问题。如果你使用<script defer src=...></script>
,你保证不打电话document.write(...)
。一个defer
外部脚本就会立即开始下载,但不会执行,直到页面之后被渲染。页面呈现后,所有defer
脚本都按照声明的顺序执行。并非所有浏览器都实现defer
了。
HTML5 introduced the async
attribute which may execute any time--possibly before the page has finished parsing or even before other defer
/async
scripts that are still downloading. But it's harder to use multiple async
scripts because their execution order is not guaranteed. Like defer
, not all browsers implement async
yet.
HTML5 引入了async
可以在任何时间执行的属性——可能在页面完成解析之前,甚至在其他defer
/async
仍在下载的脚本之前。但是使用多个async
脚本比较困难,因为它们的执行顺序没有保证。就像defer
,并非所有浏览器都实现async
了。
After all defer
and async
scripts have executed, the DOMContentLoaded
and load
events fire.
在执行完所有defer
和async
脚本之后,将触发DOMContentLoaded
和load
事件。
A brief history of defer
and async
简史defer
和async
- 1997 IE 4 introduces
defer
. - 1998 HTML 4 spec mentions
defer
, but unfortunately it doesn't say exactly whendefer
scripts execute (All in order? Beforeonload
?). Thus, no other browsers implementdefer
because no one wants to reverse-engineer IE's behavior or break scripts that might depend on IE's peculiarities. (See the Mozilla feature request, for example). - 2006 HTML5 draft finally describes the details needed to implement
defer
:defer
scripts should all be executed in order after the rest of the page is parsed, and beforeonload
. It also introducesasync
to specify scripts that can execute whenever they are downloaded without having to wait for each other. Unfortunately, HTML5 contradicts IE by not allowing inlinedefer
scripts. This breaks the invariantthat alldefer
scripts are executed in order (if somedefer
scripts havesrc
and some have inline content). - 2009 Gecko 1.9.1 (Firefox 3.5) supports
defer
. - 2010-01 Gecko 1.9.2 (Firefox 3.6) supports
async
. - 2010-09
defer
andasync
are checked into Webkit. You should see it in Chrome and Safari very soon (it's already in the Chrome dev channel but it's a bit buggy). - We're still waiting for Opera to implement
defer
andasync
and for IE to implementasync
.
- 1997 IE 4 引入
defer
. - 1998 年的HTML 4 规范提到了
defer
,但不幸的是它没有准确说明defer
脚本执行的时间(全部按顺序?之前onload
?)。因此,没有其他浏览器实现,defer
因为没有人想对 IE 的行为进行逆向工程或破坏可能取决于 IE 特性的脚本。(例如,请参阅Mozilla 功能请求)。 - 2006 HTML5 草案最终描述了实现所需的细节
defer
:defer
所有脚本都应该在页面其余部分解析之后和之前按顺序执行onload
。它还引入async
了指定可以在下载时执行的脚本,而无需彼此等待。不幸的是,HTML5 不允许内联defer
脚本与 IE 相矛盾。这打破了所有defer
脚本按顺序执行的不变性(如果某些defer
脚本src
具有内联内容,而某些脚本具有内联内容)。 - 2009 Gecko 1.9.1 (Firefox 3.5)支持
defer
. - 2010-01 Gecko 1.9.2 (Firefox 3.6)支持
async
. - 2010-09
defer
并async
签入 Webkit。你应该很快就会在 Chrome 和 Safari 中看到它(它已经在 Chrome 开发者频道中,但它有点问题)。 - 我们仍在等待 Opera 的实现
defer
和async
IE 的实现async
。
So what should a web developer use?
那么 Web 开发人员应该使用什么?
There's no single rule to follow at this time. You have to choose the solution that best balances simplicity, page render latency, and script execution latency for the set of browsers that access your website.
目前没有单一的规则可以遵循。您必须为访问您网站的浏览器集选择最能平衡简单性、页面呈现延迟和脚本执行延迟的解决方案。
- The simplest way to have the page render before the scripts execute, as others have pointed out, is to put your scripts at the bottom of the page. But if the scripts are essential, or the webpage contains lots of HTML, then you should put your scripts higher up on the page.
- If your script is standalone and your customers use IE or new versions of Firefox, use
<script async defer src=...></script>
: This allows rendering to continue in parallel to script downloading for IE and the newest HTML5 browsers but causes pre-HTML5 browsers (including all versions of Opera) to block. - If one external script depends on another, mark them both
defer
(but notasync
) and they will be executed in the order that they were declared (except IE<=9 in certain conditions can execute them out of order). Again, this allows rendering to continue in parallel to script downloading in IE and HTML5-aware Gecko/Webkit, but older browsers and Opera will suffer. It's a good idea to usedefer
even if the scripts are at the bottom of the page so that they download in parallel with each other. - Never use
defer
for inline scripts because the HTML5 draft has taken away the execution order guarantee. - If your audience includes many Opera or old Firefox/Safari users, the following snippet will execute the script after parsing the document on most pre-HTML5 browsers (IE, Webkit, need to test old Firefox), while the newest HTML5-aware browsers start downloading immediately but won't block to execute the script because of the
async
attribute. In other words, most older browsers treat it like a script at the bottom of the page, and newest browsers recognize theasync
. But Opera users get the worst of both worlds, because Opera begins execution immediately and doesn't understandasync
. This is the pattern recommended by Google Analyticsfor the urchin on many webpages.
- 正如其他人指出的那样,在脚本执行之前呈现页面的最简单方法是将脚本放在页面底部。但是,如果脚本是必不可少的,或者网页包含大量 HTML,那么您应该将脚本放在页面的更高位置。
- 如果您的脚本是独立的并且您的客户使用 IE 或新版本的 Firefox,请使用
<script async defer src=...></script>
:这允许呈现与 IE 和最新的 HTML5 浏览器的脚本下载并行继续,但会导致 HTML5 之前的浏览器(包括所有版本的 Opera)被阻止. - 如果一个外部脚本依赖于另一个,标记它们
defer
(但不是async
),它们将按照它们声明的顺序执行(除了IE<=9 在某些情况下可以乱序执行它们)。同样,这允许渲染在 IE 和支持 HTML5 的 Gecko/Webkit 中与脚本下载并行继续,但旧的浏览器和 Opera 会受到影响。defer
即使脚本位于页面底部,也最好使用这些脚本,以便它们彼此并行下载。 - 永远不要
defer
用于内联脚本,因为 HTML5 草案已经取消了执行顺序保证。 - 如果您的受众包括许多 Opera 或旧的 Firefox/Safari 用户,以下代码段将在大多数 HTML5 之前的浏览器(IE、Webkit,需要测试旧的 Firefox)上解析文档后执行脚本,而最新的支持 HTML5 的浏览器启动立即下载但不会因为该
async
属性而阻止执行脚本。换句话说,大多数较旧的浏览器将其视为页面底部的脚本,而最新的浏览器会识别async
. 但是 Opera 用户得到了两全其美的结果,因为 Opera 立即开始执行并且不理解async
. 这是Google Analytics在许多网页上为海胆推荐的模式。
snippet:
片段:
<script>
(function() {
var script = document.createElement('script');
script.src = '...';
script.async = true;
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(script, s);
})();
</script>
- If another script depends on the first script to load, then you can use the same pattern as above, but listen to the onload event of the first script element before executing the second script. See the LABjs example for how to wait for another script to load.
- If you have multiple scripts with complicated dependencies, use LAB.jsor the YUI Loaderto make them download in parallel and execute in some valid order.
- If you're using a popular library such as jQuery, consider using Google's copyrather than your own to increase the likelihood that the browser has already cached it.
- 如果另一个脚本依赖于要加载的第一个脚本,那么您可以使用与上述相同的模式,但在执行第二个脚本之前先侦听第一个脚本元素的 onload 事件。有关如何等待另一个脚本加载的信息,请参阅LABjs 示例。
- 如果您有多个具有复杂依赖关系的脚本,请使用LAB.js或YUI Loader使它们并行下载并以某种有效顺序执行。
- 如果您使用的是流行的库,例如 jQuery,请考虑使用Google 的副本而不是您自己的副本,以增加浏览器已经缓存它的可能性。
Update: If you have scripts split into modules and want to improve performance, I recommend the "Coupling Asynchronous Scripts" chapter of Even Faster Web Sitesby Steve Souder. It contains tips/tricks for not only controlling execution order but also to delay parsing of scripts to improve performance.
更新:如果您将脚本拆分为模块并希望提高性能,我建议您阅读Steve Souder 所著的Even Faster Web Sites的“耦合异步脚本”一章。它包含的提示/技巧不仅可以控制执行顺序,还可以延迟脚本解析以提高性能。
回答by Moin Zaman
defer
is supported only by internet explorer. you don't need to rely on it. there are other ways to get the same effect, like placing your scripts at the end of the page just before the </body>
tag, as others have pointed out.
defer
仅受 Internet Explorer 支持。你不需要依赖它。还有其他方法可以获得相同的效果,例如将您的脚本放在页面末尾的</body>
标记之前,正如其他人所指出的那样。
The purpose of defer is to tell the externally linked script to wait until the page finishes loading until it runs. The same thing can be accomplished via good unobtrusive JavaScript methods, which usually include code that prevents scripts from executing until the DOM is finished loading.
The advantage of defer occurs in connection with Internet Explorer, since that browser is the only one that supports the defer attribute. So, if you need a quick script to run only in IE, and you don't mind if the entire page loads before it starts to execute, then simply add defer="defer" in your tag and that will quickly take care of that problem. Fixing a transparent PNG issue in IE6 is one possible practical use for defer.
The defer attribute must be used when hiding a script from other browsers with a conditional comment that targets an IE-only script — otherwise the script will run normally in other browsers.)
defer 的目的是告诉外部链接的脚本等待页面加载完成,直到它运行。同样的事情可以通过良好的不显眼的 JavaScript 方法来完成,这些方法通常包含阻止脚本在 DOM 完成加载之前执行的代码。
defer 的优点是与 Internet Explorer 相关联,因为该浏览器是唯一支持 defer 属性的浏览器。因此,如果您需要一个仅在 IE 中运行的快速脚本,并且您不介意整个页面是否在开始执行之前加载,那么只需在您的标签中添加 defer="defer" 即可快速解决这个问题问题。修复 IE6 中的透明 PNG 问题是 defer 的一种可能的实际用途。
当使用针对 IE 专用脚本的条件注释对其他浏览器隐藏脚本时,必须使用 defer 属性 - 否则脚本将在其他浏览器中正常运行。)
Reference: http://www.impressivewebs.com/10-javascript-quick-tips-and-best-practices/
参考:http: //www.impressivewebs.com/10-javascript-quick-tips-and-best-practices/
回答by Russell Dias
If scripts can be deferred, they can also be moved to the bottom of the page (as pointed out by @Christian in the comments)
如果脚本可以推迟,它们也可以移动到页面底部(正如@Christian 在评论中指出的那样)
This would be a better choice in terms of performance, as it will not block the rest of the page from loading. You can place your scripts before the </body>
tag.
就性能而言,这将是更好的选择,因为它不会阻止页面的其余部分加载。您可以将脚本放在</body>
标记之前。
This attribute is poorly supported by major browsers, this in itself should be a hint to stop using it.
主要浏览器对这个属性的支持很差,这本身应该是一个停止使用它的提示。