关于 <script>
标签的属性 async
和 defer
,我有几个问题,据我所知只能在HTML5浏览器中使用 .
我的一个网站有两个外部JavaScript文件,目前位于 </body>
标签上方;第一个是来自谷歌的jquery,第二个是本地外部脚本 .
尊重网站加载速度
-
将
async
添加到页面底部的两个脚本中是否有任何优势? -
将
async
选项添加到两个脚本并将它们放在<head>
页面的顶部是否有任何优势? -
这是否意味着他们在页面加载时下载?
-
我认为这会导致HTML4浏览器的延迟,但是它会加速HTML5浏览器的页面加载吗?
使用<script defer src = ...
-
使用
defer
属性加载<head>
中的两个脚本与使用</body>
之前的脚本具有相同的效果吗? -
我再次假设这会降低HTML4浏览器的速度 .
使用<script async src = ...
如果我有两个启用了 async
的脚本
-
他们会同时下载吗?
-
或者与页面其余部分一次一个?
-
脚本的顺序是否会成为问题?例如,一个脚本依赖于另一个脚本,因此如果下载速度更快,则第二个脚本可能无法正确执行等 .
最后,我最好保留原样,直到HTML5更常用?
7 回答
此图像解释了正常的脚本标记,异步和延迟
异步脚本在加载脚本后立即执行,因此不保证执行顺序(最后包含的脚本可能在第一个脚本文件之前执行)
延迟脚本保证它们在页面中出现的执行顺序 .
参考链接:http://www.growingwiththeweb.com/2014/02/async-vs-defer-attributes.html
在
</body>
之前保持您的脚本正确 . 在几种情况下,异步可以与位于那里的脚本一起使用(参见下面的讨论) . Defer不会对位于那里的脚本产生太大影响,因为DOM解析工作已经完成了很多工作 .这篇文章解释了异步和延迟之间的区别:http://peter.sh/experiments/asynchronous-and-deferred-javascript-execution-explained/ .
如果您在
</body>
之前将脚本保留在正文末尾,那么您的HTML将在旧浏览器中更快地显示 . 因此,为了保持旧版浏览器的加载速度,您不希望将它们放在其他任何位置 .如果您的第二个脚本依赖于第一个脚本(例如,您的第二个脚本使用第一个脚本中加载的jQuery),那么您无法在没有其他代码来控制执行顺序的情况下使它们异步,但是您可以使它们延迟,因为延迟脚本将仍然按顺序执行,直到文档被解析后才执行 . 如果您拥有该代码并且不需要立即运行脚本,则可以使它们异步或延迟 .
您可以将脚本放在
<head>
标记中并将它们设置为defer
,并且脚本的加载将推迟到DOM已被解析,并且将在支持延迟的新浏览器中获得快速页面显示,但它实际上赢了't help you at all in older browsers and it isn' t比在所有浏览器中都适用的</body>
之前放置脚本更快 . 所以,你可以看到为什么最好在</body>
之前把它们放好 .当您在脚本加载时真的不关心并且用户所依赖的其他任何内容都不依赖于该脚本加载时,Async会更有用 . 最常被引用的使用异步的示例是像Google Analytics这样的分析脚本,您不需要等待任何事情,并且不急于即将运行并且它是独立的,因此没有其他任何依赖它 .
通常jQuery库不适合async,因为其他脚本依赖它并且你想安装事件处理程序,所以你的页面可以开始响应用户事件,你可能需要运行一些基于jQuery的初始化代码来 Build 初始状态的页面 . 它可以用作异步,但是其他脚本必须编码才能在加载jQuery之前执行 .
HTML5:
async
,defer
在HTML5中,您可以告诉浏览器何时运行JavaScript代码 . 有3种可能性:
如果没有
async
或defer
,浏览器将立即运行您的脚本,然后再渲染脚本标记下方的元素 .使用
async
(异步),浏览器将继续加载HTML页面并在浏览器加载时呈现它并同时执行脚本 .使用
defer
,浏览器将在页面完成解析后运行您的脚本 . (不必完成下载所有图像文件 . 这很好 . )async
和defer
脚本都会立即开始下载而不会暂停解析器,并且都支持可选的onload
处理程序来解决执行初始化的常见需求,这取决于脚本 .async
和之间的区别defer
以脚本执行时为中心 . 每个async
脚本在完成下载之后和窗口加载事件之前的第一个机会执行 . 这意味着async
脚本可能(并且可能)不按页面中出现的顺序执行 . 而另一方面,defer
脚本保证按照它们在页面中出现的顺序执行 . 解析完成后,但在文档的DOMContentLoaded
事件之前,执行开始 .来源及进一步细节:here .
面对同样的问题,现在清楚地了解两者是如何工作的 . 希望这个参考链接会有所帮助......
Async
将async属性添加到脚本标记时,将发生以下情况 .
进行并行请求以获取文件 .
继续解析文档,就好像它从未中断过一样 .
下载文件时执行各个脚本 .
Defer
Defer非常类似于一个主要差异的异步 . 这是当浏览器遇到带有defer属性的脚本时发生的情况 .
生成并行请求以获取单个文件 .
继续解析文档,就好像它从未中断过一样 .
即使脚本文件已下载,也要完成解析文档 .
按照文档中遇到的顺序执行每个脚本 .
参考:Difference between Async and Defer
似乎延迟和异步的行为依赖于浏览器,至少在执行阶段 . 注意,延迟仅适用于外部脚本 . 我假设异步遵循相同的模式 .
在IE 11及更低版本中,顺序似乎是这样的:
异步(页面加载时可部分执行)
none(页面加载时可以执行)
延迟(在页面加载后执行,所有按照文件中的放置顺序延迟)
在Edge,Webkit等中,async属性似乎被忽略或放在最后:
data-pagespeed-no-defer(在加载页面之前,在任何其他脚本之前执行)
无(可在页面加载时执行)
defer(等待DOM加载,所有按顺序放置在文件中)
async(似乎要等到DOM加载)
在较新的浏览器中,data-pagespeed-no-defer属性在任何其他外部脚本之前运行 . 这适用于不依赖于DOM的脚本 .
注意:当您需要外部脚本的明确执行顺序时,请使用延迟 . 这告诉浏览器按照放置在文件中的顺序执行所有延迟脚本 .
ASIDE:外部javascripts的大小在加载时很重要......但对执行顺序没有影响 .
如果您担心脚本的性能,可能需要考虑缩小或简单地使用XMLHttpRequest动态加载它们 .
async
和defer
将在HTML解析期间下载该文件 . 两者都不会中断解析器 .具有
async
属性的脚本将在下载后执行 . 具有defer
属性的脚本将在完成DOM解析后执行 .使用
async
加载的脚本不保证任何订单 . 加载defer
属性的脚本维护它们在DOM上的显示顺序 .当脚本不依赖任何内容时,请使用
<script async>
. 当脚本依赖使用时 .最好的解决方案是添加在body的底部 . 阻塞或渲染没有问题 .
UPDATE
答案已根据评论予以纠正 .