一次完整的HTTP請求過程
域名解析 --> 發起TCP的3次握手 --> 建立TCP連接后發起http請求 --> 服務器響應http請求,瀏覽器得到html代碼 --> 瀏覽器解析html代碼,並請求html代碼中的資源(如js、css、圖片等) --> 瀏覽器對頁面進行渲染呈現給用戶
頁面解析過程
CSS
不會阻塞DOM
解析,但是會阻塞DOM
渲染,嚴謹一點則是CSS
會阻塞render tree
的生成,進而會阻塞DOM
的渲染JS
會阻塞DOM
解析CSS
會阻塞JS
的執行- 瀏覽器遇到
<script>
標簽且沒有defer
或async
屬性時會觸發頁面渲染(渲染出來元素后才方便js獲取元素,雖然瀏覽器在未執行js時,並不知道該js是否要操作元素)- css是異步下載的,不會阻塞dom解析
- js的下載會阻塞dom解析
關於最后兩條
css可以異步是因為css不會操作dom的結構,只是樣式罷了,所以dom繼續解析產生更多而元素之類的不會有任何影響,但是如果是js,則有可能js會改變目前已經出現的dom的結構,所以必須立刻暫停解析,下載好之后去執行.
- 獲取HTML文件,對其進行DOM解析
- 如果遇到css文件,並行下載並解析CSSOM
- 遇到js文件,立即下載並暫停dom解析,如果css的link在js的link的上面,則會等到CSSOM解析完成后再立刻執行js,注意此時DOM的解析一直處於停止狀態,如果js的link在css的上面,則會先執行js,不用等待CSSDOM解析完成,但是js執行時DOM和CSSOM都是暫停解析的
請求html后會進行DOM構建,過程中遇到css引用會並行請求css並且進行cssom構建,當DOM和CSSOM構建完成,渲染樹會進行合並渲染,但是如果過程中出現js引用並且沒有使用async標簽,則會停止dom樹解析,先執行js
為什么一定要等CSSOM解析完成才能執行js,不能像DOM一樣停下來呢?
因為CSSOM不能部分解析,也就是說,DOM解析出來多少就業以渲染出來多少(遇到js就會觸發渲染,詳情見上面),而CSS則不行,因為可能解析到一半,某個字體是16px,但是在最后的css里,會設置為10px,這時候js操作的文件就是不正確的.
為什么js一定要停下來先執行,而不是等待dom解析完成再執行?
JS經常會操縱DOM,影響到UI。
想一想瀏覽器在下載頁面期間會發生什么事——頁面開始(按文檔結構)渲染時,突然遇到一個<script>
標簽。這時瀏覽器只能停止渲染,來加載這個JavaScript,因爲該腳本內容可能會影響/決定后續的UI。JavaScript加載完會立即執行,對頁面造成影響(or not)后,瀏覽器再繼續渲染頁面UI
script為何放在body后?如何優化
原因 放在后面是防止阻塞dom的渲染
優化
window.onload
:當頁面 DOM 結構中的 js、css、圖片,以及 js 異步加載的 js、css 、圖片都加載完成之后,才會觸發 load 事件。DOMContentLoaded
:在 html文檔加載完畢,並且 html 所引用的內聯 js、以及外鏈 js 的同步代碼都執行完畢后觸發。- 采用
async
和defer
async和defer的區別
script 標簽 | JS 執行順序 | 是否阻塞解析 HTML |
---|---|---|
<script> |
在 HTML 中的順序 | 阻塞 |
<script async> |
網絡請求返回順序 | 可能阻塞,也可能不阻塞 |
<script defer> |
在 HTML 中的順序 | 不阻塞 |
默認script標簽
async
defer