我想使用defer
和async
加载以下JavaScript代码:
<script defer async src="/js/somescript.js"></script>
由于defer
受Internet Explorer 5.5+的支持,正如你在CanIUse.com所看到的,如果async不可用,我想优雅地使用defer。 Async我认为最好在可用时使用,但在Internet Explorer 10之前不支持。
我的问题是上面的代码是否有效HTML?如果没有,是否有可能使用JavaScript优雅地回退到defer
不可用时在脚本上使用async
来创建这种情况?
从规格:https://www.w3.org/TR/2011/WD-html5-20110525/scripting-1.html#attr-script-async
即使指定了async属性,也可以指定defer属性,以使仅支持延迟(而非异步)的旧Web浏览器回退到延迟行为而不是默认的同步阻塞行为。
问题是,你期望它做什么?如果同时存在异步和延迟,我希望脚本被延迟并且只在浏览器空闲时在DOMContentLoaded之后执行,但是如果我正在读取规范,如果设置了异步并且加载了脚本,则看起来像defer被忽略异步,因此一旦可用就会执行,这可能在DOMContentLoaded之前执行,并可能阻止其他资源。
可以使用这些属性选择三种可能的模式。如果存在async属性,则脚本一旦可用就会异步执行。如果async属性不存在但是存在defer属性,则在页面完成解析时执行脚本。如果两个属性都不存在,则在用户代理继续解析页面之前立即获取并执行脚本。
https://www.w3.org/TR/2011/WD-html5-20110525/scripting-1.html#attr-script-async
是的,它的有效HTML和它将按预期工作。
任何符合W3C标准的浏览器都将识别async属性并正确处理脚本,而旧版IE将识别defer属性。
由于两个属性都是布尔值,因此您不必分配任何值。
不幸的是,当defer
指定时,async
被忽略,而async
总是具有更高的优先级。 (至少在Chrome中。老实说,没有在其他浏览器中测试过,但我认为结果会是一样的。)
而且我个人认为defer
被忽略是非常糟糕的。让我们想象一下,当我们想要一些JS初始化ASAP时,甚至在加载页面内容之前。但我们希望在其他需要它的脚本之前初始化此脚本。它应该是defer
队列中的第一个。但是,不幸的是,这不起作用:
<!-- we want "jQuery" ASAP and still in "defer" queue. But defer is ignored. -->
<script src="jquery.min.js" async defer></script>
<!-- this doesn't blocks the content and can wait the full page load, but requires "jQuery" -->
<script src="some_jquery_plugin.min.js" defer></script>
在此示例中,可以在加载jQuery之前加载并执行“some_jquery_plugin.min.js”,并且将失败。 :(
所以有两种方法可以解决这个问题:要么只使用defer
指令,要么将所有依赖javascript的文件合并到单个JS中。