今天有啥理由不使用 <script defer> 吗?

Posted

技术标签:

【中文标题】今天有啥理由不使用 <script defer> 吗?【英文标题】:Any good reason not to use <script defer> TODAY?今天有什么理由不使用 <script defer> 吗? 【发布时间】:2017-07-21 11:43:46 【问题描述】:

曾几何时,&lt;script&gt;&lt;head&gt;&lt;body&gt; 上有很多激烈的争论。

许多 SO 帖子已经指出 最佳实践 / 经验法则 是将 &lt;script&gt; 放在 &lt;body&gt; 末尾之前,以免阻塞 html 解析器,从而为客户端带来更快的首屏绘制和更快的 DOM 访问,从而获得更好的用户体验。

这一定是重复的╰(‵□′)╯

等等……&lt;script&gt; 现在可以变成deferred,实际上还有一段时间!

旧帖说

延迟脚本可能会导致 JS 依赖问题

不,不会。当 DOM 被解析时,它会立即保留执行顺序。

它不能跨供应商工作

是的,曾经是,但今天几乎所有主要浏览器供应商都支持它:http://caniuse.com/#search=defer,此外,正如 cmets 指出的那样,IE

然而,它提供的好处似乎是显而易见的,至少对我而言,因为它在更早的时间(在开始解析 DOM 之前)并行下载脚本,因此无需稍后请求脚本并缩短所需的时间带来整个页面互动

简而言之,这个问题类似于:任何不使用的充分理由

<head>
...
<script src='cdn/to/jquery' defer>
<script src='cdn/to/bootstrap' defer>
<script src='script/depends/on/jqueryandbootstrap' defer>
</head>

改用这个:

<body>
...
<script src='cdn/to/jquery'>
<script src='cdn/to/bootstrap'>
<script src='script/depends/on/jqueryandbootstrap'>
</body>

注意:这可能是一个有很多讨论的“古老”话题。然而,随着 Web 技术的快速发展,浏览器供应商与新的 Web 规范更好地保持一致,许多旧的 *** 答案可能无法保持最新​​。

【问题讨论】:

caniuse 中有一条说明 IE defer 的好理由:p Here is some good reading. 和放在head的头部没有defer一样 我差点忘了这个(defer) 魔法属性; This is an interesting article I found on Mozilla Hack defer 是否会消除对 $(document).ready() 的需求? 【参考方案1】:

是的,但这只是因为您使用的是 jQuery。

jQuery doesn't work with defer 因为它会在页面变为交互式时尝试触发。他们不能很快修复它(我在一年前提出了这个错误),因为改变准备行为以使用defer 将破坏许多依赖 jQuery 的准备事件触发交互的组件(即在延迟脚本之前)加载完毕)。

如果您使用的是更现代的框架(React、Angular 2、Polymer、Vue 或其他任何东西),那么就选择它 - 或者甚至进入下一步并在新浏览器中使用 &lt;script type=module 和IE 中 &lt;script nomodule defer... 中的旧包。

【讨论】:

要明确的是,即使我在项目中使用 jQuery,也可以使用 defer 加载任何其他 JS 库,我只是不能使用 defer 加载 jQuery 库。对吗? @dmikester1 你可以推迟任何你想要的东西,但你不能依赖 jQuery 已经加载或加载的事件。 jQuery 和所依赖的一切都必须是同步的。不仅仅是 jQuery - 任何试图挂钩 DOM 加载事件的库都可能有问题,从那个时期开始,尝试在库中跳转 DOM 加载事件有一点趋势。 作为一个具体的例子,我在这里关注谷歌的地图 API 示例:developers.google.com/maps/documentation/javascript/tutorial 他们使用asyncdefer,他们还将脚本标签放在底部。现在是最佳做法吗? @dmikester1 不,Google 的地图 API 实际上有点糟糕——它在 2009 年非常棒,但对已弃用的 IE6 等充满了黑客攻击。它不适用于 SPA 中的影子 DOM 和内存泄漏。最佳做法是 type=modulenomodule 后备,或使用动态导入。 @dmikester1 但是,您完全可以在带有 jQ​​uery 的页面上使用它,并按照该示例进行操作,它将起作用。只是不在 SPA 中。【参考方案2】:

如here 所述,您应该考虑浏览器支持,因为其中一些并不真正支持它。在某些版本中也存在一些众所周知的错误,例如 IE 中的this one

如果您的目标不是支持旧浏览器(查找完整的支持列表 here),那么今天没有理由不选择 defer。

【讨论】:

以上是关于今天有啥理由不使用 <script defer> 吗?的主要内容,如果未能解决你的问题,请参考以下文章

有啥理由不使用全局 lambda?

有啥理由不使用 JSONP?

有啥理由不使用 Visual Studio 6 for C++? [关闭]

有啥理由不放弃“var”吗?

使用 if(1 || !Foo()) 有啥理由吗?

有啥理由这不是冗余代码吗?