script的defer和async
我们常用的script标签,有两个和性能、js文件下载执行相关的属性:defer和async
defer的含义【摘自https://developer.mozilla.org/En/HTML/Element/Script】
This Boolean attribute is set to indicate to a browser that the script is meant to be executed after the document has been parsed.
async的含义【摘自https://developer.mozilla.org/En/HTML/Element/Script】
Set this Boolean attribute to indicate that the browser should, if possible, execute the script asynchronously.
?
对于defer,我们可以先思考一个情况。一个页面如果有N个外链的脚本,放在head中,那么,当加载脚本时会阻塞页面的渲染,也就是常说的空白。在简单的开发环境中,我们可能只要将源代码中的外链脚本位置换一下就ok了。可是面对越来越复杂的开发环境,前端同事如果要后台开发同事调整一下脚本的位置,可能会花费大量的沟通成本和开发成本。我在去年的一个项目中就遇到过此类情况,当然也很感谢当时的后台开发同事的配合,他们都辛辛苦苦的调整了脚本的位置,解决了空白的问题。
那么可以让这个成本降到最低吗?那么我们可以使用defer这个属性。
如果一个script加了defer属性,即使放在head里面,它也会在html页面解析完毕之后再去执行,也就是类似于把这个script放在了页面底部。
关于defer有两个demo:
简单介绍一下这个demo,一共引用了3个js和1个css,为了能更好的展示defer的效果,第二个js-2.php是延迟了3秒返回的。1.js会在页面中生成一个值为1的input框,2.php会生成值为2的input框,3.js会生成值为3的input框。一方面我们需要观察页面渲染的时间,另一方面我们也要看一下js是否顺序执行了。
下图是without_defer.html的效果,从瀑布图可以看出,domready和onload的时间都在6s左右,因为需要等待2.php的返回才能渲染页面。如果你访问上面的例子,可以看出,页面要等6s的时间才会呈现出来,6s之前都是空白。
FeatureChromeFirefox (Gecko)Internet ExplorerOperaSafariBasic support1.01.0 (1.7 or earlier)(Supported)(Supported)(Supported)async?attribute(Supported)3.6 (1.9.2)10–(Supported)defer?attribute(Supported)3.5 (1.9.1)4–(Supported)
摘自【http://dev.w3.org/html5/spec/Overview.html#attr-script-async】
There are three possible modes that can be selected using these attributes. If the async attribute is present, then the script will be executed asynchronously, as soon as it is available. If the async attribute is not present but the defer attribute is present, then the script is executed when the page has finished parsing. If neither attribute is present, then the script is fetched and executed immediately, before the user agent continues parsing the page.
简单的来说,使用这两个属性会有三种可能的情况
最后给一点个人的建议,无论使用defer还是async属性,都需要首先将页面中的js文件进行整理,哪些文件之间有依赖性,哪些文件可以延迟加载等等,做好js代码的合并和拆分,然后再根据页面需要使用这两个属性。