瀏覽器原理筆記
瀏覽器工作原理
瀏覽器架構
- 單進程,多執行緒
- 多進程,多執行緒,進程間通過IPC(Inter Process Communication)通訊
Google多進程架構
各進程的分工
- 瀏覽器進程
UI執行緒,網路執行緒,存儲執行緒…
負責瀏覽器的「Chrome」部分, 包括導航欄,書籤, 前進和後退按鈕。同時這個進程還會控制那些我們看不見的部分,包括網路請求的發送以及文件的讀寫。 - 渲染進程
主執行緒,幾個工作執行緒,合成執行緒,光柵執行緒
負責標籤頁內和網頁展示相關的所有工作 - 插件進程
控制網頁使用的所有插件,例如flash插件。 - GPU進程
負責獨立於其它進程的GPU任務。它之所以被獨立為一個進程是因為它要處理來自於不同tab的渲染請求並把它在同一個介面上畫出來。 - 擴展進程
- 工具進程
- 通過瀏覽器的任務管理器查看所有進程
多進程的優缺點
- 容錯性高,不同的tab會有不同的渲染進程來負責,所以一個標籤頁的渲染進程崩潰,其他頁面不受影響.
- Chrome採用多進程架構的另外一個好處就是可以提供安全性和沙盒性(sanboxing)。因為作業系統可以提供方法讓你限制每個進程擁有的能力,所以瀏覽器可以讓某些進程不具備某些特定的功能。例如,由於tab渲染進程可能會處理來自用戶的隨機輸入,所以Chrome限制了它們對系統文件隨機讀寫的能力
- 進程開多了耗記憶體,所以為了節省記憶體,Chrome會限制被啟動的進程數目,當進程數達到一定的界限後,Chrome會將訪問同一個網站的tab都放在一個進程裡面跑。
Chrome的服務化
- Chrome瀏覽器的架構正在發生一些改變,目的是將和瀏覽器本身(Chrome)相關的部分拆分為一個個不同的服務,服務化之後,這些功能既可以放在不同的進程裡面運行也可以合併為一個單獨的進程運行。
單幀渲染進程 – 網站隔離
- 網站隔離(Site Isolation)是最近Chrome瀏覽器啟動的功能,這個功能會為網站內不同站點的iframe分配一個獨立的渲染進程。之前說過Chrome會為每個tab分配一個單獨的渲染進程,可是如果一個tab只有一個進程的話不同站點的iframe都會跑在這個進程裡面,這也意味著它們會共享記憶體,這就有可能會破壞同源策略。同源策略是瀏覽器最核心的安全模型,它可以禁止網站在未經同意的情況下去獲取另外一個站點的數據,因此繞過同源策略是很多安全攻擊的主要目的。而進程隔離(proces isolation)是隔離網站最好最有效的辦法了。
從導航(navigation)開始
- 瀏覽器中tab外面發生的一切都是由瀏覽器進程(browser process)控制的。瀏覽器進程有很多負責不同工作的執行緒(worker thread),其中包括繪製瀏覽器頂部按鈕和導航欄輸入框等組件的UI執行緒(UI thread)、管理網路請求的網路執行緒(network thread)、以及控制文件讀寫的存儲執行緒(storage thread)等。當你在導航欄裡面輸入一個URL的時候,其實就是UI執行緒在處理你的輸入。
- UI執行緒處理輸入
- UI執行緒讓網路執行緒請求網路
- 網路執行緒讀取響應
- 尋找一個渲染進程
- 渲染進程提交(commit)導航
- 文檔載入階段開始
讀取響應階段
- 網路執行緒在收到HTTP響應的主體(payload)流(stream)時,在必要的情況下它會先檢查一下流的前幾個位元組以確定響應主體的具體媒體類型(MIME Type)。
- 如果響應的主體是一個HTML文件,瀏覽器會將獲取的響應數據交給渲染進程(renderer process)來進行下一步的工作。如果拿到的響應數據是一個壓縮文件(zip file)或者其他類型的文件,響應數據就會交給下載管理器(download manager)來處理。
- 網路執行緒在把內容交給渲染進程之前還會對內容做SafeBrowsing檢查。如果請求的域名或者響應的內容和某個已知的病毒網站相匹配,網路執行緒會給用戶展示一個警告的頁面。除此之外,網路執行緒還會做CORB(Cross Origin Read Blocking)檢查來確定那些敏感的跨站數據不會被發送至渲染進程。
…
渲染階段
將html解析為dom過程
-
創建document對象,解析html,將元素對象和文本內容添加到文檔中,此時document.readyState = ‘loading’
-
遇到link外部css的時候,創建新的執行緒非同步載入,繼續解析html
-
遇到有src的scripts(沒有async和defer標記)載入外部的js時,同步載入並阻塞解析html,而且載入完馬上執行
-
遇到設置async和defer的script,創建新的執行緒非同步載入,繼續解析html。async載入完馬上執行,defer在DOMContentLoaded前執行
-
遇到帶有src的img,解析dom結構,再非同步載入src的圖片資源,不會等待img載入完成繼續解析文檔。另外,img要等待css載入完才解碼,所以css阻塞圖片的呈現,類似於js阻塞html解析一樣。可以想一下,如果css被設置為display:none,還有意義嗎?所以此時雖然對後台有請求但不解碼
-
文檔解析完畢,document.readyState = ‘interactive’
-
此時帶有defer的js開始按順序執行
-
DOMContentLoaded觸發,程式從同步腳本執行轉化為事件驅動階段(類似ele.onclick = handel已經開始生效)
-
當所有的script載入完成並且成功執行、img和css載入完畢,document.readyState = ‘completed’,觸發onload事件
-
非同步響應ui行為,開始交互
將CSSOM和DOM合併成渲染樹
因為瀏覽器有GUI渲染執行緒與JS引擎執行緒,為了防止渲染出現不可預期的結果,這兩個執行緒是互斥的關係。
JavaScript的載入、解析與執行會阻塞DOM的構建
,也就是說,在構建DOM時,HTML解析器若遇到了JavaScript,那麼它會暫停構建DOM,將控制權移交給JavaScript引擎,等JavaScript引擎運行完畢,瀏覽器再從中斷的地方恢復DOM構建。
JS文件不只是阻塞DOM的構建,它會導致CSSOM也阻塞DOM的構建。
瀏覽器會先下載和構建CSSOM,然後再執行JavaScript,最後在繼續構建DOM。
布局與繪製
通過構造渲染樹,我們將可見DOM節點以及它對應的樣式結合起來,可是我們還需要計算它們在設備視口(viewport)內的確切位置和大小,這個計算的階段就是迴流。
迴流這一階段主要是計算節點的位置和幾何資訊,那麼當頁面布局和幾何資訊發生變化的時候,就需要迴流。
迴流一定會觸發重繪,而重繪不一定會迴流
瀏覽器工作流程:構建DOM -> 構建CSSOM -> 構建渲染樹 -> 布局 -> 繪製。
CSSOM會阻塞渲染,只有當CSSOM構建完畢後才會進入下一個階段構建渲染樹。
通常情況下DOM和CSSOM是並行構建的,但是當瀏覽器遇到一個不帶defer或async屬性的script標籤時,DOM構建將暫停,如果此時又恰巧瀏覽器尚未完成CSSOM的下載和構建,由於JavaScript可以修改CSSOM,所以需要等CSSOM構建完畢後再執行JS,最後才重新DOM構建。