我一直在为我的一个项目的HEAD部分中使用的外部脚本添加defer属性。我查询了多个延迟脚本标记的执行顺序。
以下是我的观察,这将有助于我们更好地理解我的查询:
根据http://www.w3.org/TR/html5/scripting-1.html
存在defer属性,然后在页面完成解析后执行脚本
defer属性确实有效。但是,我怀疑执行顺序。在FF和Chrome上看起来有所不同。
根据我的项目:
<script defer="defer" src="{SERVER_PATH}/deps.js?1441452359"></script>
<script defer="defer" src="{SERVER_PATH}/script1.js?1440067073"></script>
<script defer="defer" src="{SERVER_PATH}/script2.js?1441451916"></script>
这里,deps.js是大约120kb(gzip)的大文件,而script1-3的常规大小是20-50kb(gzip)。
在Firefox上,延迟编写脚本的执行确实按照外观顺序开始,但不会以相同的顺序完成。除非前一个脚本完成执行,否则在chrome上的位置,下一个脚本的执行不会启动。看起来Chrome很有意义。
为了测试执行顺序,我在每个脚本的第一行和最后一行插入了console.log,例如在deps.js
console.log("Execution Start: deps");
// minified deps script content.
console.log("Execution End: deps");
Firefox下的控制台输出下方:
Execution Start: deps
Execution Start: script1
Execution Start: script2
// Script Error as script1 needs deps to render completely.
// Script Error as script2 needs deps to render completely.
Execution End: deps
Chrome控制台输出下方:
Execution Start: deps
Execution End: deps
Execution Start: script1
Execution End: script1
Execution Start: script2
Execution End: script2
但是,FF上的行为并不总是如上所示。有时它确实像Chrome一样工作。它看起来像只是Firefox的问题。或者,可能是因为deps.js文件很重且缩小并且需要时间来渲染。
任何有类似经历的人都可以帮助我吗?如果需要任何其他信息,请告诉我。
PS:其他解决方案,例如,移动页面底部的脚本不是我现在正在看的东西。
答案 0 :(得分:6)
HTML5.0规范说:
如果元素具有src属性,并且元素具有defer属性,并且该元素已标记为“parser-inserted”,并且该元素没有async属性
必须将元素添加到脚本列表的末尾,这些脚本将在文档完成与创建元素的解析器的Document相关联的解析时执行。
一旦获取算法完成,网络任务源在任务队列上放置的任务必须设置元素的“准备好解析器执行”标志。解析器将处理执行脚本。
所以它确实说它推迟了脚本执行,直到解析了相关的Document
,它还说它被推入列表中。因此,列表的顺序应该是在解析插入脚本顺序时。
然而,第二部分让我担心。它基本上说它只会被标记为执行,直到网络任务finsihed下载脚本。然后......“解析器将处理执行脚本”。
我在规范中找不到的是文档解析后的脚本执行情况。它是否继续以列表顺序执行脚本,因为它们“准备好被解析器执行”?或者它会等到列表中的所有脚本“准备好执行解析器”然后执行它们。
规范(步骤15):http://www.w3.org/TR/html5/scripting-1.html#script-processing-src-prepare
答案 1 :(得分:0)
我认为除非“执行结束”日志发生在与“执行开始”日志不同的事件循环中,否则这是不可能的。
你能确保我们吗?否则就意味着Firefix在这里做了一些多线程,而且正如我们所知,JS没有支持。