關於外部樣式表的阻塞問題
外部樣式表會不會阻塞文件解析?
不會。
style-sheets 不會修改 DOM 樹,沒有理由為了解析 style-sheets 而阻塞文件解析(即 style-sheets 不會阻塞文件解析)。但如果在解析文件過程中有指令碼需要訪問樣式資訊時,為了保證訪問樣式資訊的正確性。Firefox 會阻塞所有指令碼直到 style-sheets 下載解析完為止。而 WebKit 只在訪問的樣式屬性沒有被載入解析時,才會阻塞指令碼。
即 style-sheet 不會直接阻塞文件解析,它只阻塞 script 的解析執行,才導致 style-sheet 間接阻塞文件解析。
總結
- style-sheet 預設情況下是不會阻塞文件解析。
- style-sheet 只會阻塞 script 指令碼解析執行。
關於 Script 的載入順序
使用方式
-
內嵌 JS 程式碼
<script> function sayScript() { alert("<\/script>"); } </script> 複製程式碼
注意:在標籤內寫程式碼時,不能出現字串"",如果要用,也只能通過轉義來解決。
-
引用外部檔案
<script src="example.js"></script> // OR <script src="example.js" /> 複製程式碼
注意:
<script>
預設type
就是 "text/javascript"。因此無需顯示寫出來。
載入順序
在解釋 <script>
內的程式碼時,頁面中其他內容都不會被瀏覽器載入或顯示。同樣,在下載外部檔案和解析外部檔案時,頁面的處理會暫時停止。注意,script 的特性是載入了並執行裡面的指令碼,然後再載入並執行下一個 script。
只要不存在 defer
和 async
屬性,瀏覽器都會按照 <script>
元素在頁面中出現的先後順序對它們依次進行解析。
瀏覽器是單程式執行 JS 和載入 JS 的,並且解析 HTML 也是單程式的,是阻塞的。直觀的感受有,彈窗時頁面會“卡住”,載入時頁面會白屏。
為什麼需要順序載入和執行?
因為 JS 有可能修改 DOM,如果不阻塞後續的資源下載,DOM 的操作順序不可控。
如何降低這種阻塞的影響?
可以將 <script>
放在 <body>
的最後。一方面,這樣可以使頁面儘快渲染;另一方面,在 DOM 結構生成之前操作 DOM,可能會報錯。
defer 和 async
補充:當初始的 HTML 文件被完全載入和解析完成之後,DOMContentLoaded 事件被觸發,而無需等待樣式表、影象和子框架的完成載入。
初步理解
-
defer
英語的意思就是推遲,延遲。那麼顧名思義,就是延遲指令碼執行的意思。指令碼會被延遲到整個頁面解析完再執行。
相當於告訴瀏覽器:立即下載,但是延遲執行。
-
async
目的是不讓頁面等待指令碼下載和執行,而是非同步載入頁面其他內容。
屬性效果
二者都會並行下載,不會影響頁面的解析。
defer
會按照順序在 DOMContentLoaded 前按照頁面出現順序依次執行。async
下載完立即執行。不保證按照指定的先後順序執行。
進一步理解
-
defer
可以認為是將外鏈的js放在了頁面底部。js的載入不會阻塞頁面的渲染和資源的載入。不過defer會按照原本的js的順序執行,所以如果前後有依賴關係的js可以放心使用。 -
async
能夠非同步的載入和執行指令碼,不因為載入指令碼而阻塞頁面的載入。一旦載入到就會立刻執行在有async的情況下,js一旦下載好了就會執行,所以很有可能不是按照原本的順序來執行的。如果js前後有依賴性,用async,就很有可能出錯。另外,建議非同步指令碼不要在載入期間修改 DOM。
參考
-
《JavaScript 高階程式設計》(第3版)
-
《徹底搞懂 async & defer》github.com/xiaoyu2er/b…