Script載入順序 & 外部樣式表的阻塞

小皮草發表於2018-09-04

關於外部樣式表的阻塞問題

外部樣式表會不會阻塞文件解析?

不會。

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

只要不存在 deferasync 屬性,瀏覽器都會按照 <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

參考

相關文章