Chrome中主要的進程有四個:
瀏覽器進程 (Browser Process):負責(zé)瀏覽器的TAB的前進、后退、地址欄、書簽欄的工作和處理瀏覽器的一些不可見的底層操作,比如網(wǎng)絡(luò)請求和文件訪問。
渲染進程 (Renderer Process):負責(zé)一個Tab內(nèi)的顯示相關(guān)的工作,也稱渲染引擎。
插件進程 (Plugin Process):負責(zé)控制網(wǎng)頁使用到的插件
GPU進程 (GPU Process):負責(zé)處理整個應(yīng)用程序的GPU任務(wù)
由于進程與進程之間內(nèi)存空間獨立,所以需要進程之間的通信需要使用新的方式——IPC通信
4個進程之間的關(guān)系:
當(dāng)我們要瀏覽一個網(wǎng)頁時,輸入URL,瀏覽器進程向URL發(fā)送請求,獲取到HTML內(nèi)容后將其交給渲染進程,渲染進程解析HTML內(nèi)容,解析中遇到新的網(wǎng)絡(luò)資源再返回給瀏覽器進程加載,同時告知瀏覽器進程需要通知插件進程加載插件。解析完成后,渲染進程計算得到圖像幀,將圖像幀交給GUP進程,GUP進程將圖像顯示出來。
多進程架構(gòu)的好處:
1.容錯性高,渲染引擎容易崩潰,多進程的每個頁面的渲染引擎互相之間不受影響;
2.安全性高,不同進程的權(quán)限不同,并為其提供沙盒運行環(huán)境,使其更加安全可靠;
3.響應(yīng)速度快,單進程架構(gòu)中各個任務(wù)互相競爭搶奪CPU資源,響應(yīng)速度緩慢,多進程架構(gòu)規(guī)避了這一點。
導(dǎo)航過程:
網(wǎng)頁加載過程:
tab以外的大部分工作都是瀏覽器進程負責(zé)的,分為幾個不同的工作線程:
UI線程:控制瀏覽器上的按鈕以及輸入框;
網(wǎng)絡(luò)線程:處理網(wǎng)絡(luò)請求,獲取網(wǎng)絡(luò)數(shù)據(jù);
storage線程:控制文件的訪問;
第一步:處理輸入
在地址欄輸入內(nèi)容按下回車,UI線程會判斷輸入的內(nèi)容是搜索關(guān)鍵詞還是URL,并作出對應(yīng)的處理;
第二步:開始導(dǎo)航
UI線程把對應(yīng)任務(wù)交給網(wǎng)絡(luò)線程,tab前的圖標展示為加載中狀態(tài),網(wǎng)絡(luò)線程進行DNS尋址,建立TLS連接等操作進行資源請求,如果服務(wù)器301重定向,則告知UI線程進行重定向再進行新的網(wǎng)絡(luò)請求。
第三步:讀取響應(yīng)
網(wǎng)絡(luò)線程接收到服務(wù)器的響應(yīng)后解析HTTP報文,根據(jù)響應(yīng)頭中的Content-Type字段來確定響應(yīng)主體的媒體類型,如果媒體類型是HTML文件,就將相應(yīng)數(shù)據(jù)交給渲染進程進行接下來的工作,如果是zip等文件,就會把數(shù)據(jù)交給下載管理器。(與此同時,瀏覽器會進行Safe Browsing安全檢查展示警告頁和CORB檢查確定敏感跨站數(shù)據(jù)不被發(fā)送至渲染進程)
第四步:查找渲染進程
上面的準備都完成之后,網(wǎng)絡(luò)線程通知UI線程數(shù)據(jù)已經(jīng)準備好了,此時UI線程會查找到一個UI進程進行網(wǎng)頁渲染。(第二步開始的時候瀏覽器已經(jīng)預(yù)先查找和啟動了一個渲染進程)
第五步:提交導(dǎo)航
到了這一步,數(shù)據(jù)和渲染進程都準備好了,瀏覽器進程會向渲染進程發(fā)送IPC消息來確認導(dǎo)航,同時將準備好的數(shù)據(jù)發(fā)送給渲染進程,渲染進程接收到數(shù)據(jù)后,又發(fā)送IPC消息給瀏覽器進程,表示導(dǎo)航已經(jīng)提交了,頁面開始加載。這時導(dǎo)航欄會更新,安全提示符更新(小鎖),訪問歷史列表(history tab)更新,即可通過前進和后退來切換該頁面。
第六步:初始化加載完成
提交導(dǎo)航完成后,渲染進程開始記載資源及渲染頁面,當(dāng)頁面渲染完成后(頁面及內(nèi)部的iframe都觸發(fā)了onload事件),回想瀏覽器進程發(fā)送IPC消息,此時UI線程會停止tab中加載的圖標。
網(wǎng)頁渲染原理:
五個步驟:
第一步:處理 HTML 并構(gòu)建 DOM 樹。
引擎解析HTML,解析的結(jié)果會成為一顆DOM樹,這顆DOM樹將會作為下個階段渲染樹狀圖的輸入以及成為網(wǎng)頁和腳本的交互界面(js操作DOM)
當(dāng)解析器到達script標簽時,發(fā)生下面四件事情:
1.html解析器停止解析,
2.如果是外部腳本,就從外部網(wǎng)絡(luò)獲取腳本代碼
3.將控制權(quán)交給js引擎,執(zhí)行js代碼
4.恢復(fù)html解析器的控制權(quán)
由于<script>標簽是阻塞解析的,將腳本放在網(wǎng)頁尾部會加速代碼渲染。
defer和async屬性也能有助于加載外部腳本。
defer使得腳本會在dom完整構(gòu)建之后執(zhí)行;
async標簽使得腳本只有在完全available才執(zhí)行,并且是以非阻塞的方式進行的
第二步:處理 CSS構(gòu)建 CSSOM 樹。
css樣式表是阻塞的,當(dāng)cssom樹建立好之后才會進行下一步的解析渲染。
通過以下手段可以減輕cssom帶來的影響:
1.將script腳本放在頁面底部
2.盡可能快的加載css樣式表
3.將樣式表按照media type和media query區(qū)分,這樣有助于我們將css資源標記成非阻塞渲染的資源。
4.非阻塞的資源還是會被瀏覽器下載,只是優(yōu)先級較低
第三步:將 DOM 與 CSSOM 合并成一個渲染樹。
第四步:根據(jù)渲染樹來布局,計算每個節(jié)點的位置。
布局(layout):定位坐標和大小,是否換行,各種position, overflow, z-index屬性
第五步:調(diào)用 GPU 繪制,合成圖層,顯示在屏幕上。
將渲染樹的各個節(jié)點繪制到屏幕上,這一步被稱為繪制painting
渲染性能優(yōu)化:
Load 和 DOMContentLoaded 區(qū)別:
Load 事件觸發(fā)代表頁面中的 DOM,CSS,JS,圖片已經(jīng)全部加載完畢。
DOMContentLoaded 事件觸發(fā)代表初始的 HTML 被完全加載和解析,不需要等待 CSS,JS,圖片加載
圖層:
一般來說,可以把普通文檔流看成一個圖層。特定的屬性可以生成一個新的圖層。不同的圖層渲染互不影響,所以對于某些頻繁需要渲染的建議單獨生成一個新圖層,提高性能。但也不能生成過多的圖層,會引起反作用。
以下幾個屬性可以生成新圖層:
translate3d、translateZ
will-change
video、iframe
通過動畫實現(xiàn)opacity動畫轉(zhuǎn)換
position: fixed
重繪和回流:
重繪是當(dāng)前節(jié)點布局不發(fā)生變化但外觀發(fā)生變化的,比如color的改變就是重繪
回流是布局或者幾何屬性需要改變。
(重繪和回流屬于渲染的一部分,但這兩個步驟對于性能影響頗大,
回流必定發(fā)生重繪,重繪不一定引發(fā)回流。回流成本很大,改變深層次的節(jié)點很可能導(dǎo)致父節(jié)點的一系列回流。)
下面幾個動作會導(dǎo)致性能:
改變window大?。?/p>
改變字體;
添加或刪除樣式;
文字改變;
定位或者浮動;
盒子模型;
參考文獻: