前言已烤、瀏覽器架構(gòu)
Chrome主要使用多進(jìn)程架構(gòu)磁玉,各個進(jìn)程互相獨立,具有各自所負(fù)責(zé)的功能中鼠,若要互相通信則采用IPC機制進(jìn)行通信可婶。
1.瀏覽器主進(jìn)程:主要負(fù)責(zé)主界面顯示,用戶交互援雇,各個進(jìn)程管理
2.網(wǎng)絡(luò)進(jìn)程:負(fù)責(zé)網(wǎng)絡(luò)資源下載和與渲染進(jìn)程進(jìn)行資源傳輸
3.渲染進(jìn)程:子資源的加載矛渴,頁面解析
4.GPU進(jìn)程:GPU渲染加速,能夠針對css的一些屬性進(jìn)行性能優(yōu)化惫搏,使用GPU進(jìn)行繪制
5.插件進(jìn)程:管理插件使用和執(zhí)行
1具温、DNS解析
當(dāng)我們輸入域名例如:www.baidu.com的時候,瀏覽器會首先調(diào)用器本地的DNS客戶端來解析這個域名筐赔,因為http協(xié)議的底層tcp/ip協(xié)議只能夠識別到ip格式的地址铣猩,有了ip地址我們就能正確地識別到目標(biāo)服務(wù)器并開始發(fā)送數(shù)據(jù)。
那么什么是DNS呢茴丰,它是域名系統(tǒng)(Domain Name System)达皿,負(fù)責(zé)將域名解析成ip地址天吓,由根服務(wù)器,頂級服務(wù)器峦椰,二級服務(wù)器(權(quán)威DNS服務(wù)器)等組成龄寞,分層地逐步地將域名解析出來,那么接下來說下瀏覽器將域名解析成ip的過程汤功。
瀏覽器會先查找本地的DNS緩存有沒該域名記錄物邑,若要則返回,無則向系統(tǒng)緩存進(jìn)行查找
若系統(tǒng)緩存有該域名的DNS記錄冤竹,則返回拂封,無則向本地的DNS服務(wù)器查找
本地的DNS可能是你搭建的dns服務(wù)或者路由器提供的服務(wù)茬射,在本地的DNS服務(wù)器緩存進(jìn)行查找鹦蠕,無則向上一層的本地DNS服務(wù)器發(fā)起查詢
無本地dns服務(wù)器都沒有改記錄,則向互聯(lián)網(wǎng)運營商DNS緩存進(jìn)行查找
互聯(lián)網(wǎng)運營商也無該記錄的話則向域名系統(tǒng)服務(wù)器發(fā)起查詢在抛,由根域名服務(wù)器钟病,.com頂級域名服務(wù)器,.baidu.com二級域名服務(wù)器來進(jìn)行遞歸查詢刚梭,通常到這里就有該dns記錄并返回ip地址
注:DNS主要基于UDP傳輸層協(xié)議肠阱,一次UDP名字服務(wù)器交換可以短到兩個包:一個查詢包、一個響應(yīng)包朴读。一次TCP交換則至少包含9個包:三次握手初始化TCP會話屹徘、一個查詢包、一個響應(yīng)包以及四次分手的包交換衅金≡胍粒考慮到效率原因,TCP連接的開銷大氮唯,故采用UDP作為DNS的運輸層協(xié)議鉴吹,這也將導(dǎo)致只有13個根域名服務(wù)器的結(jié)果。(UDP不能保證數(shù)據(jù)傳輸?shù)目煽啃猿土穑矡o法避免接受到重復(fù)數(shù)據(jù)的情況)
2豆励、HTTP連接
收到ip地址后就可以發(fā)送http請求了,http的請求報文包括狀態(tài)行瞒渠,請求頭和請求消息報文良蒸,由傳輸層通過tcp/ip協(xié)議轉(zhuǎn)化成數(shù)據(jù)包,經(jīng)過網(wǎng)絡(luò)層伍玖、鏈路層嫩痰、物理層后再向上逐層遞交和轉(zhuǎn)化在應(yīng)用層里返回給服務(wù)器,服務(wù)器取得數(shù)據(jù)處理后私沮,發(fā)送響應(yīng)報文包括狀態(tài)行始赎,響應(yīng)頭和響應(yīng)消息報文和橙,這樣瀏覽器就獲取到響應(yīng)數(shù)據(jù)。
三次握手
http協(xié)議是基于tcp/ip協(xié)議造垛,而在開始數(shù)據(jù)傳輸之前會先進(jìn)行tcp的通道連接魔招,通過3次握手來確定是否連接成功。
- 第一次握手:客戶端發(fā)送SYN(synchronous建立聯(lián)機)為1五辽,seq(順序號碼)為隨機數(shù)x办斑,發(fā)送到服務(wù)端,要求建立連接
- 第二次握手:服務(wù)端接收SYN為1的建立連接請求杆逗,便向客戶端發(fā)送確認(rèn)請求乡翅,SYN為1,ACK(acknowledgement 確認(rèn))為1罪郊,seq為隨機數(shù)y蠕蚜,ack(確認(rèn)號碼)為x+1
- 第三次握手:客戶端接收到確認(rèn)請求,便會校驗ack是否為x+1悔橄,若正確則發(fā)送ACK為1靶累,ack為y+1,至此tcp連接建立成功
四次揮手
數(shù)據(jù)傳輸完成后會通過四次揮手來結(jié)束連接癣疟。
- 第一次揮手:客戶端向服務(wù)器發(fā)送FIN為1挣柬,seq為隨機數(shù)x,表示已經(jīng)沒任何數(shù)據(jù)發(fā)送了
- 第二次揮手:服務(wù)端接收到客戶端的FIN包睛挚,表示接收到客戶端關(guān)閉連接的請求邪蛔,但還沒完全關(guān)閉,此時向客戶端發(fā)送ACK為1扎狱,ack為x+1
- 第三次揮手:當(dāng)服務(wù)端做好完全關(guān)閉連接的準(zhǔn)備時侧到,會再向客戶端發(fā)送FIN為1,seq為隨機數(shù)y
- 第四次揮手:客戶端收到服務(wù)端結(jié)束關(guān)閉的請求后委乌,向服務(wù)端發(fā)送ACK為1床牧,ack為y+1,等待2MSL(2 Maximum Segment Lifetime)遭贸,若再沒收到服務(wù)端的響應(yīng)戈咳,便結(jié)束連接,至此四次揮手連接關(guān)閉
3壕吹、頁面渲染
構(gòu)建DOM樹
瀏覽器不能夠直接識別到html的文件著蛙,它要首先將html文件轉(zhuǎn)換成一種數(shù)據(jù)結(jié)構(gòu)的類型-樹,我們將這個生成后的類似樹狀結(jié)構(gòu)數(shù)據(jù)稱為DOM耳贬,每個元素表示DOM上的一個節(jié)點踏堡,瀏覽器遍歷這些節(jié)點渲染成頁面元素。
構(gòu)建CSS STYLESHEETS
同樣道理咒劲,瀏覽器會將css轉(zhuǎn)換為一種瀏覽器可以理解的結(jié)構(gòu)styleSheets顷蟆,再與DOM樹結(jié)合诫隅,構(gòu)成了具有樣式的布局樹,對應(yīng)節(jié)點上會有相應(yīng)的樣式帐偎。這里的布局樹會去掉隱藏的節(jié)點逐纬,只有真實顯示的節(jié)點
布局階段
有了布局樹就可以將元素渲染到頁面上,樣式的渲染遵循層疊繼承規(guī)則削樊,當(dāng)我們需要修改樣式的時候豁生,這里面的布局涉及重排和重繪
回流(reflow)(重排)
頁面重新渲染,重新布局漫贞,修改dom的寬高甸箱,位置會觸發(fā)
重繪(repaint): 頁面重新繪制,例如修改字體顏色迅脐,背景等
回流需要重新計算布局芍殖,耗費性能,而重繪只是局部更新仪际,性能渲染較小围小£侵瑁回流必定會觸發(fā)重繪树碱,而重繪不一定需要回流。
在操作DOM的時候变秦,我們應(yīng)該盡可能地減少回流和重繪成榜,降低性能損耗
GUI渲染線程
接下來我們主要分析GUI渲染線程執(zhí)行的詳細(xì)過程:
1. 解析HTML文件,構(gòu)建DOM樹蹦玫,同時瀏覽器主進(jìn)程負(fù)責(zé)下載CSS文件
2. CSS文件下載完成赎婚,解析CSS文件成樹形的數(shù)據(jù)結(jié)構(gòu),然后結(jié)合DOM樹合并成RenderObject樹
3. 布局RenderObject樹樱溉,負(fù)責(zé)RenderObject樹中的元素尺寸挣输,位置等計算
4. 繪制RenderObject樹,繪制頁面的像素信息
5. 瀏覽器主進(jìn)程將默認(rèn)圖層和復(fù)合圖層交給GPU進(jìn)程福贞,GPU進(jìn)程再將各個圖層合成(composite)撩嚼,最后顯示出頁面
注:
- 默認(rèn)圖層指的就是處于普通文檔流的元素;
- 復(fù)合圖層一般指使用動畫執(zhí)行或者
<video><iframe><canvas><webgl>
等元素挖帘,也可以使用z-index將層級高的元素變成復(fù)合圖層完丽,使用復(fù)合圖層可以進(jìn)行硬件加速,其原理就是避免了默認(rèn)圖層的重繪和回流拇舀,想了解的童鞋可以自行深入研究逻族。
了解GUI渲染線程的執(zhí)行過程后,我們可以根據(jù)其渲染原理進(jìn)行渲染優(yōu)化:
- 盡可能提前引入css文件骄崩,例如在頭部引入css文件;
- 盡可能早加載css文件中引用的資源聘鳞,例如自定義字體文件薄辅,可以使用預(yù)加載,在link標(biāo)簽加入’rel=”preload” as=”font”‘該元素屬性,不然會造成渲染阻塞
- 在DOM和CSS渲染之后加載js文件抠璃,例如在尾部加載js文件长搀,或者使用該元素屬性”defer”和”async”,進(jìn)行js文件異步加載,但是在不同瀏覽器會有兼容性問題鸡典。