singsong: 文章中 demo 猛戳这里吧
在讲解以前,先看一个问题。以下图所示,外部样式表是否会阻塞 HTML 解析(先不要看答案,能够本身思考和实验一下):html
经过DevTools->network:html5
如上图所示,indexcss.css 并无阻塞 HTML 解析,由于 DOMContentLoaded 时间线在 indexcss.css 以后。但若是在 indexcss.css 以后添加script 标签(不能为空),结果会同样?git
经过 DevTools->network:github
如上图所示,在 indexcss.css 以后添加 script 标签(不能为空)后,此时 DOMContentLoaded 时间线位于 indexcss.css 以后。说明这里 indexcss.css 是阻塞 HTML 解析的。web
Style sheets on the other hand have a different model. Conceptually it seems that since style sheets don't change the DOM tree, there is no reason to wait for them and stop the document parsing. There is an issue, though, of scripts asking for style information during the document parsing stage. If the style is not loaded and parsed yet, the script will get wrong answers and apparently this caused lots of problems. It seems to be an edge case but is quite common. Firefox blocks all scripts when there is a style sheet that is still being loaded and parsed. WebKit blocks scripts only when they try to access certain style properties that may be affected by unloaded style sheets.---- Tali Garsiel
大概意思是:style-sheets 不会修改 DOM 树,没有理由为了解析 style-sheets 而阻塞文档解析(即 style-sheets 不会阻塞文档解析)。但若是在解析文档过程当中有脚本须要访问样式信息时,为了保证访问样式信息的正确性。Firefox 会阻塞全部脚本直到 style-sheets 下载解析完为止。而 WebKit 只在访问的样式属性没有被加载解析时,才会阻塞脚本。app
也即 style-sheet 不会直接阻塞文档解析,它只阻塞 script 的解析执行,才致使 style-sheet 间接阻塞文档解析。若是将 script 设置为非阻塞式的呢?能够经过为 script 标签设置 aysnc 特性来实现。可能你会疑问为何不用 defer?异步
Both async and defer scripts begin to download immediately without pausing the parser and both support an optional onload handler to address the common need to perform initialization which depends on the script. The difference between async and defer centers around when the script is executed. Each async script executes at the first opportunity after it is finished downloading and before the window’s load event. This means it’s possible (and likely) that async scripts are not executed in the order in which they occur in the page. The defer scripts, on the other hand, are guaranteed to be executed in the order they occur in the page. That execution starts after parsing is completely finished, but before the document’s DOMContentLoaded event.
大概意思:async 和 defer 特性在脚本开始下载时,都不会阻塞文档解析。而且都支持 onload 事件回调处理,用于一些初始化工做。另外,二者对内联脚本都无效,脚本中不能调用document.write()
。而二者的不一样之处:带有 async 特性的脚本会在脚本下载完后当即执行,且在 load 事件以前,因此不能确保脚本在文档中出现的顺序来执行。而带有defer特性的脚本会在文档解析完后按照在文档中出现的顺序来执行,且在 DOMContentLoaded 事件以前。async
所以,这里设置 async 特性,而不设置 defer 特性。为了尽早地触发 DOMContentLoaded 事件,由于 defer 会延迟 DOMContentLoaded 事件触发。性能
为 script 标签添加 async 特性:
经过DevTools->network:
固然,这里也能够经过媒体查询 media让 style-sheet 异步加载:
经过DevTools->network: