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: