我們在瀏覽器輸入網址后,瀏覽器會向服務器發送請求,服務器將請求的HTML文檔發送回瀏覽器,瀏覽器將文檔下載下來后,便開始從上到下解析,解析完成之后,會生成DOM。如果頁面中有css,會根據css的內容形成CSSOM,然后DOM和CSSOM會生成一個渲染樹,最后瀏覽器會根據渲染樹的內容計算出各個節點在頁面中的確切大小和位置,並將其繪制在瀏覽器上。
在頁面加載解析html的時候,會產生中斷,這是因為JavaScript會阻塞dom解析,轉而取處理腳本,如果腳本是內聯的,將先執行此腳本;如果是外聯的,則先加載腳本然后再執行。然后再進行html解析。
當文檔中沒有腳本時,瀏覽器解析完文檔便能觸發 DOMContentLoaded 事件;如果文檔中包含腳本,則腳本會阻塞文檔的解析,而腳本需要等位於腳本前面的css加載完才能執行。在任何情況下,DOMContentLoaded 的觸發不需要等待圖片等其他資源加載完成。
注意:js會受到css樣式的限制,如果有css,先進行css加載解析之后再執行腳本文件。這是因為js需要知道對象的樣式。
DOMContentLoad和Load不同點在於:
1.DOMContentLoaded
是HTML文檔(CSS、JS)被加載以及解析完成之后觸發(即 HTML->DOM
的過程完成 );
2.load需要在頁面的圖片、視頻等加載完后被觸發,而DOMContent不需要等待這些資源加載完成;
3.一般情況下,load在DOMContent解析完之后才被觸發(有可能在其前面觸發);
針對頁面的優化:
將js放到body標簽底部,原因是因為瀏覽器生成Dom樹的時候是逐行讀取HTML代碼,script標簽放在最后面就不會影響前面的頁面的渲染。那么問題來了,既然Dom樹完全生成好后頁面才能渲染出來,瀏覽器又必須讀完全部HTML才能生成完整的Dom樹,script標簽不放在body底部是不是也一樣,因為dom樹的生成需要整個文檔解析完畢。
在頁面渲染過程中的,First Paint(第一渲染)的時間。頁面的paint不是在渲染樹生成之后嗎?其實現代瀏覽器為了更好的用戶體驗,渲染引擎將嘗試盡快在屏幕上顯示的內容。它不會等到所有HTML解析之前開始構建和布局渲染樹。部分的內容將被解析並顯示。也就是說瀏覽器能夠渲染不完整的dom樹和cssom,盡快的減少白屏的時間。假如我們將js放在header,js將阻塞解析dom,dom的內容會影響到First Paint,導致First Paint延后。所以說我們會將js放在后面,以減少First Paint的時間,但是不會減少DOMContentLoaded被觸發的時間。