瀏覽器渲染——html頁面外聯script會阻塞頁面渲染嗎?


注:測試瀏覽器為chrome瀏覽器

我們先來看第一段代碼:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>測試</title>
    </head>
    <body>
        <h1>Hello</h1>
        <script type="text/javascript">
            let i = 1000000000
            while(i>0){
                i-- 
            }
        </script>
        <h1>world</h1>
    </body>
</html>

 我們知道js會阻塞DOM解析和渲染,所以頁面肯定會在內聯script里的代碼執行完成之后,再渲染出來

答案確實是這樣

分析:一開始渲染進程的HTML 解析器開始解析DOM,當解析到內聯script 腳本標簽時,HTML 解析器會暫停解析DOM,此時JavaScript 引擎介入,並執行內聯script 標簽中的這段腳本,腳本執行完成之后,HTML 解析器恢復解析過程,繼續解析DOM,然后進行后續的渲染,最終將頁面上同時渲染出 Hello World

 

接下來,我們看第二段代碼:

index.js:

var i = 1000000000
while(i>0){
    i--
}

index.html:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>測試</title>
    </head>
    <body>
        <h1>Hello</h1>
        <script type="text/javascript" src="index.js"></script>
        <h1>world</h1>
    </body>
</html>

那這段html代碼的運行結果是不是和上面一樣呢?

剛開始我以為是,后來發現並不是這樣的,谷歌瀏覽器做了一些優化,所以執行結果會有一些變化

分析:當渲染引擎收到字節流之后,會開啟一個預解析線程,用來分析 HTML 文件中包含的 JavaScript、CSS 等相關文件,解析到相關文件之后,預解析線程會提前下載這些文件。因為這段html代碼里有外聯script腳本,所以會丟到預解析線程去下載這個外聯js文件,此時HTML 解析器開始解析DOM,當遇到外聯script標簽時,停止DOM解析,瀏覽器會渲染一次頁面(當前的Hello會被渲染到頁面上),然后執行下載完成的js文件,接着繼續解析DOM,然后進行后續的渲染,最終將頁面上就會渲染出 Hello World

注意:這里是先渲染出Hello ,然后過一會兒(這個期間在執行js),再渲染出World

 

答案:第一段代碼和第二段代碼的執行最終結果一樣,但是渲染順序不一樣。第一段代碼先間隔一段時間(執行js),然后Hello World會同時被渲染出來;第二段代碼會先渲染出Hello,然后間隔一段時間(執行js),再渲染出World

總結:

  雖然js都會阻塞DOM解析,但是瀏覽器對於內聯script和外聯script的渲染過程還是有一點點不同。內聯js會阻塞DOM解析和渲染,直到js執行完成后,頁面才會被渲染出來。外聯js也會阻塞DOM解析和渲染,但是如果在外聯script標簽之前已經有DOM元素生成,則瀏覽器會優先渲染一次。我想這是因為瀏覽器不知道腳本的內容,因而碰到腳本時,只好先渲染頁面,確保腳本能獲取到最新的DOM元素信息,盡管腳本可能不需要這些信息。

 

 

——個人理解,如有出錯,請指正——  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM