一:為什么要了解瀏覽器渲染頁面和加載頁面機制,主要還是性能的優化。
- 了解瀏覽器如何進行加載,我們可以在引用外部樣式文件,外部js時,將他們放到合適的位置,使瀏覽器以最快的速度將文件加載完畢。
- 了解瀏覽器如何進行解析,我們可以在構建DOM結構,組織css選擇器時,選擇最優的寫法,提高瀏覽器的解析速率。
- 了解瀏覽器如何進行渲染,明白渲染的過程,我們在設置元素屬性,編寫js文件時,可以減少”重繪“”重新布局“的消耗。
這三個過程在實際進行的時候又不是完全獨立,而是會有交叉。會造成一邊加載,一邊解析,一邊渲染的工作現象。
二:用戶訪問網頁都發生了什么。
- 用戶訪問網頁,DNS服務器(域名解析系統)會根據用戶提供的域名查找對應的IP地址,找到后,系統會向對應IP地址的網絡服務器發送一個http請求。
- 網絡服務器解析請求,並發送請求給數據庫服務器。
- 數據庫服務器將請求的資源返回給網絡服務器,網絡服務器解析數據,並生成html文件,放入http response中,返回給瀏覽器。
- 瀏覽器解析 http response。
- 瀏覽器解析 http response后,需要下載html文件,以及html文件內包含的外部引用文件,及文件內涉及的圖片或者多媒體文件。(這里進入主題了也就是下面的第三大點)
1~4步驟HTTP協議的一些內容,訪問服務器端可能遭遇的問題:如果網絡服務器無法獲取數據庫服務器返回的資源文件(http response 404),或者由於並發原因暫時無法處理用戶的http請求(http response 500)。
三:瀏覽器渲染頁面和解析加載頁面機制。
a.加載,即為獲取資源文件的過程,不同瀏覽器,以及他們的不同版本在實現這一過程時,會有不同的實現效果(資源間互相阻塞,可以用timeline來做測試)。這里先說下瀏覽器的5個常駐線程:
- 瀏覽器GUI渲染線程
- javascript引擎線程
- 瀏覽器定時器觸發線程(setTimeout)
- 瀏覽器事件觸發線程
- 瀏覽器http異步請求線程(.jpg <link />這類請求)
備注:現代瀏覽器存在 prefetch 優化,瀏覽器會另外開啟線程,提前下載js、css文件,需要注意的是,預加載js並不會改變dom結構,他將這個工作留給主加載。
注意:這里也涉及到 阻塞 的現象,當js引擎線程(第二個)進行時,會掛起其他一切線程,這個時候3、4、5這三類線程也會產生不同的異步事件,由於 javascript引擎線程為單線程,所以代碼都是先壓到隊列,采用先進先出的方式運行,事件處理函數,timer函數也會壓在隊列中,不斷的從隊頭取出事件,這就叫:javascript-event-loop。簡單點說應該是當在進行第二線程的時候,1,3,4,5都會掛起,比如這時候觸發click事件,即使先前JS已經加載完成,click事件會壓在隊列里,這里也要先完成第二線程才會執行click事件。
加載順序:
- 瀏覽器解析http response 下載html文件會”自上而下“加載,並在加載過程中進行解析渲染。“自上而下”加載時遇到圖片、視頻之類資源時便會進入第5個線程,這是異步請求,並不會影響html文檔進行加載。
- 加載過程中遇到外部css文件,瀏覽器另外發出一個請求,來獲取css文件。這里也是第5個線程,這里css解析會生成一個rule tree(規則樹),這個以后會更新。
- 當文檔加載過程中遇到js文件,html文檔會掛起渲染(加載解析渲染同步)的線程,不僅要等待文檔中js文件加載完畢,還要等待解析執行完畢,才可以恢復html文檔的渲染線程。
原因:JS有可能會修改DOM,最為經典的document.write,這意味着,在JS執行完成前,后續所有資源的下載可能是沒有必要的,這是js阻塞后續資源下載的根本原因。
辦法:可以將外部引用的js文件放在</body>前。
4. css可能影響js的執行造成阻塞。
原因:如js里面var width = $('#id').width();這里js執行前,瀏覽器必須保證之前的css文件已下載和解析完成(后面的不會影響),這也是css阻塞后續js的根本原因。當js文件不需要依賴css文件時,可以將js文件放在頭部css的前面。
5. 預加載網頁,利用空余時間來提前加載該網頁的后續網頁。
<link rel="prefetch" href="http://">
6. 為js腳本添加defer屬性,其不會阻塞后續DOM的的渲染。但是因為這個defer只是IE專用,所以一般用得比較少。而我們標准的的HTML5也加入了一個異步載入javascript的屬性:async,無論你對它賦什么樣的值,只要它出現,它就開始異步加載js文件。但是, async的異步加載會有一個比較嚴重的問題,那就是它忠實地踐行着“載入后馬上執行”這條軍規,所以,雖然它並不阻塞頁面的渲染,但是你也無法控制他執行的次序和時機。
<script defer="true" src="JavaScript.js" type="text/javascript"/>
mark--zhq[2]。
