先看一下標準定義的瀏覽器渲染過程(網上找的):
用戶第一次訪問網址,瀏覽器向伺服器發出請求,伺服器返回html檔;
瀏覽器開始載入html程式碼,發現head 標籤內有一個link 標籤引用外部CSS或JS檔案;
瀏覽器又發出CSS及JS檔案的請求,伺服器回傳這個CSS,JS檔案;
瀏覽器繼續載入html中body 部分的程式碼,並且CSS,JS檔案已經拿到手了,可以開始渲染頁面了;
瀏覽器在程式碼中發現一個img 標籤引用了一張圖片,向伺服器發出請求。 此時瀏覽器不會等到圖片下載完,而是繼續渲染後面的程式碼;
伺服器返回圖片文件,由於圖片佔用了一定面積,影響了頁面佈局,因此瀏覽器需要回頭重新渲染這部分代碼;
瀏覽器發現了一個包含一行Javascript代碼的script 標籤,趕快執行它;
Javascript腳本執行了這條語句,它命令瀏覽器隱藏掉代碼中的某個p (style.display=”none”)。杯具啊,突然就少了這麼一個元素,瀏覽器不得不重新渲染這部分程式碼;
終於等到了html 的到來,瀏覽器淚流滿面…
IE瀏覽器下載的順序是從上到下,渲染的順序也是從上到下,下載和渲染是同時進行的。
在渲染到頁面的某一部分時,其上面的所有部分都已經下載完成(並不是說所有相關聯的元素都已經下載完)
如果遇到語義解釋性的標籤嵌入檔案(JS腳本,CSS樣式),那麼此時IE的下載過程會啟用單獨連線進行下載。
並且在下載後進行解析,解析過程中,停止頁面所有往下元素的下載,阻塞加載。
樣式表在下載完成後,將和先前下載的所有樣式表一起進行解析,解析完成後,將對此前所有元素(含以前已經渲染的)重新進行渲染。
JS、CSS中如有重定義,後定義函數將覆寫前定義函數。
不能並行下載和解析(阻塞下載)
web的模式是同步的,開發者希望解析到一個腳本標籤時並執行一個腳本,的解析直到腳本執行完;如果腳本是外引的,當引用了JS的時候,瀏覽器發送一個js request就會一直等待該request的返回,這個過程也是同步的,會阻塞文檔的解析直到資源被請求到。因為瀏覽器需要一個穩定的DOM樹結構,而JS中很有可能有程式碼直接改變了DOM樹結構,例如使用document.write 或appendChild,甚至是直接使用的location.href進行跳轉,瀏覽器為了防止出現JS修改DOM樹,需要重新建構DOM樹的情況,所以就會阻塞其他的下載和呈現。這個模式維持了很多年,並且在html4及html5中都特別指定了。開發者可以將腳本標識為defer,使其不阻塞文件解析,並在文件解析結束後執行。 Html5增加了標記腳本為非同步的選項,以使腳本的解析執行使用另一個執行緒。
這裡面有幾點需要說明一下:
1.我們知道瀏覽器的處理過程是解析html生成DOM tree->根據DOM tree和樣式表生成render tree->render展示。瀏覽器為了讓使用者更快的看到頁面,所以是邊解析html產生局部的DOM tree,瀏覽器就產生部分render tree然後展示出來。
2.此過程中有兩種外部資源是阻塞腳本執行,從而阻塞渲染的,分別是外部js和外部css。 外部js是阻塞了DOM tree的生成,因為瀏覽器需要一個穩固的DOM tree,而js可能破壞這個結構(當然其中也可能會更改樣式【注意是樣式而不是樣式表】,但是這個不阻塞也不會有影響的);外部css樣式表也會阻塞腳本的執行,理論上,既然樣式表不改變Dom樹,也就沒有必要停下文檔的解析等待它們,然而,存在一個問題,腳本可能在文檔的解析過程中請求樣式信息,如果樣式還沒有加載和解析,腳本將得到錯誤的值,顯然這將會導致很多問題,這看起來是個邊緣情況,但確實很常見。 Firefox在存在樣式表還在載入和解析時阻塞所有的腳本,而Chrome只在當腳本試圖存取某些可能被未載入的樣式表所影響的特定的樣式屬性時才阻塞這些腳本。
3.其他外部資源是不阻塞渲染的,比如圖片,我們能看到很多時候頁面大體的框架都呈現出來了,就是圖片的位置沒有顯示出來的情況,等到圖片下載下來以後再重新渲染。
現代瀏覽器的最佳化:
依照標準的瀏覽器渲染下載流程。下面的程式碼載入外部資源的順序應該和資源在html中的順序一致。其中head添加了一個外部資源請求http://m.sbmmt.com/hm.js?a041a0f4ff93aef6aa83f34134331a1d㟎ee 但是實際上在chrome。 Firefox、ie8+等瀏覽器中卻發現是以下效果(使用https://www.webpagetest.org/測試)
為什麼?這就是預解析(Speculative parsing)Webkit和Firefox都做了這個優化,當執行腳本時,另一個線程解析剩下的文檔,並加載後面需要通過
網絡加載的資源 。這種方式可以使資源並行載入從而使整體速度更快。要注意的是,預解析並不會改變Dom樹,它將這個工作留給主解析過程,自己只解析外部資源的引用,例如外部腳本、樣式表及圖片。 如上面的那張圖,可以看出在執行腳本的時候與解析了一大堆的外部資源引用,並啟動線程下載他們,主線程還在等待hm.js的返回。
以上就是瀏覽器載入和渲染HTML的過程(標準定義的過程以及現代瀏覽器的最佳化)的內容,更多相關內容請關注PHP中文網(m.sbmmt.com)!