- 用戶輸入U(xiǎn)RL匙隔,瀏覽器會(huì)根據(jù)用戶輸入的信息判斷是搜索還是網(wǎng)址疑苫,如果是搜索內(nèi)容,就將搜索內(nèi)容+默認(rèn)搜索引擎合成新的URL;如果用戶輸入的內(nèi)容符合URL規(guī)則捍掺,瀏覽器就會(huì)根據(jù)URL協(xié)議撼短,在這段內(nèi)容上加上協(xié)議合成合法的URL
- 用戶輸入完內(nèi)容,按下回車鍵挺勿,瀏覽器導(dǎo)航欄顯示loading狀態(tài)曲横,但是頁面還是呈現(xiàn)前一個(gè)頁面,這是因?yàn)樾马撁娴捻憫?yīng)數(shù)據(jù)還沒有獲得
- 瀏覽器進(jìn)程瀏覽器構(gòu)建請(qǐng)求行信息不瓶,會(huì)通過進(jìn)程間通信(IPC協(xié)議(進(jìn)程通信協(xié)議))將URL請(qǐng)求發(fā)送給網(wǎng)絡(luò)進(jìn)程
- 網(wǎng)絡(luò)進(jìn)程獲取到URL禾嫉,先去本地緩存中查找是否有緩存文件,如果有蚊丐,攔截請(qǐng)求熙参,直接返回200(from cache) ;否則麦备,進(jìn)入網(wǎng)絡(luò)請(qǐng)求過程
- 網(wǎng)絡(luò)進(jìn)程請(qǐng)求DNS返回域名對(duì)應(yīng)的IP和端口號(hào)孽椰,如果之前DNS數(shù)據(jù)緩存服務(wù)緩存過當(dāng)前域名信息,就會(huì)直接返回緩存信息泥兰;否則弄屡,發(fā)起請(qǐng)求獲取根據(jù)域名解析出來的IP和端口號(hào),如果沒有端口號(hào)鞋诗,http默認(rèn)80膀捷,https默認(rèn)443。如果是https請(qǐng)求削彬,還需要建立TLS連接全庸。
- Chrome 有個(gè)機(jī)制,同一個(gè)域名同時(shí)最多只能建立 6 個(gè)TCP 連接融痛,如果在同一個(gè)域名下同時(shí)有 10 個(gè)請(qǐng)求發(fā)生壶笼,那么其中 4 個(gè)請(qǐng)求會(huì)進(jìn)入排隊(duì)等待狀態(tài),(優(yōu)化這個(gè)問題的辦法在這里[https://www.sojson.com/blog/98.html])(https://www.sojson.com/blog/98.html)
雁刷,直至進(jìn)行中的請(qǐng)求完成覆劈。如果當(dāng)前請(qǐng)求數(shù)量少于6個(gè),會(huì)直接建立TCP連接沛励。 - TCP三次握手建立連接责语,http請(qǐng)求加上TCP頭部——包括源端口號(hào)、目的程序端口號(hào)和用于校驗(yàn)數(shù)據(jù)完整性的序號(hào)目派,向下傳輸
- 網(wǎng)絡(luò)層在數(shù)據(jù)包上加上IP頭部——包括源IP地址和目的IP地址坤候,繼續(xù)向下傳輸?shù)降讓?/li>
- 底層通過物理網(wǎng)絡(luò)傳輸給目的服務(wù)器主機(jī)
- 目的服務(wù)器主機(jī)網(wǎng)絡(luò)層接收到數(shù)據(jù)包,解析出IP頭部企蹭,識(shí)別出數(shù)據(jù)部分白筹,將解開的數(shù)據(jù)包向上傳輸?shù)絺鬏攲?/li>
- 目的服務(wù)器主機(jī)傳輸層獲取到數(shù)據(jù)包智末,解析出TCP頭部,識(shí)別端口徒河,將解開的數(shù)據(jù)包向上傳輸?shù)綉?yīng)用層
- 應(yīng)用層HTTP解析請(qǐng)求頭和請(qǐng)求體系馆,如果需要重定向,HTTP直接返回HTTP響應(yīng)數(shù)據(jù)的狀態(tài)code301或者302虚青,同時(shí)在請(qǐng)求頭的Location字段中附上重定向地址它呀,瀏覽器會(huì)根據(jù)Location進(jìn)行重定向操作;如果不是重定向棒厘,首先服務(wù)器會(huì)根據(jù) 請(qǐng)求頭中的If-None-Match 的值來判斷請(qǐng)求的資源是否被更新纵穿,如果沒有更新,就返回304狀態(tài)碼奢人,協(xié)商緩存谓媒,相當(dāng)于告訴瀏覽器之前的緩存還可以使用,就不返回新數(shù)據(jù)了何乎;否則句惯,返回新數(shù)據(jù),200的狀態(tài)碼支救,并且如果想要瀏覽器緩存數(shù)據(jù)的話抢野,就在相應(yīng)頭中加入字段:Cache-Control:Max-age=?各墨,響應(yīng)數(shù)據(jù)返回到網(wǎng)絡(luò)進(jìn)程指孤。
- 數(shù)據(jù)傳輸完成,TCP四次揮手?jǐn)嚅_連接贬堵。如果恃轩,瀏覽器或者服務(wù)器在HTTP頭部加上如下信息(Connection:Keep-Alive ),TCP就一直保持連接黎做。保持TCP連接可以省下下次需要建立連接的時(shí)間叉跛,提示資源加載速度
- 網(wǎng)絡(luò)進(jìn)程將獲取到的數(shù)據(jù)包進(jìn)行解析,根據(jù)響應(yīng)頭中的Content-type來判斷響應(yīng)數(shù)據(jù)的類型蒸殿,如果是字節(jié)流類型筷厘,就將該請(qǐng)求交給下載管理器(屬于瀏覽器進(jìn)程),該導(dǎo)航流程結(jié)束宏所,不再進(jìn)行酥艳;如果是text/html類型或者其他類型,就通知瀏覽器進(jìn)程獲取到文檔準(zhǔn)備渲染
-
瀏覽器進(jìn)程獲取到通知楣铁,根據(jù)當(dāng)前頁面B是否是從頁面A打開玖雁,并且和頁面A是否是同一個(gè)站點(diǎn)(根域名和協(xié)議一樣就被認(rèn)為是同一個(gè)站點(diǎn))更扁,如果滿足上述條件盖腕,就復(fù)用之前網(wǎng)頁的進(jìn)程赫冬,否則,新創(chuàng)建一個(gè)單獨(dú)的渲染進(jìn)程
image.png
- 瀏覽器會(huì)發(fā)出“提交文檔”的消息給渲染進(jìn)程溃列,渲染進(jìn)程收到消息后劲厌,會(huì)和網(wǎng)絡(luò)進(jìn)程建立傳輸數(shù)據(jù)的“管道”,文檔數(shù)據(jù)傳輸完成后听隐,渲染進(jìn)程會(huì)返回“確認(rèn)提交”的消息給瀏覽器進(jìn)程
- 瀏覽器收到“確認(rèn)提交”的消息后补鼻,會(huì)更新瀏覽器的頁面狀態(tài),包括了安全狀態(tài)雅任、地址欄的 URL风范、前進(jìn)后退的歷史狀態(tài),并更新web頁面沪么,此時(shí)的web頁面還是空白頁,接下來就到了渲染進(jìn)程來工作了硼婿。
瀏覽器渲染進(jìn)程主要流程
-
渲染進(jìn)程對(duì)文檔進(jìn)行頁面解析和子資源加載,
1.渲染進(jìn)程將HTML內(nèi)容轉(zhuǎn)換為能夠讀懂的DOM樹結(jié)構(gòu)
2.渲染引擎將CSS樣式表轉(zhuǎn)化為瀏覽器可以理解的styleSheets,計(jì)算出DOM節(jié)點(diǎn)的樣式禽车。
3.創(chuàng)建布局樹寇漫,并計(jì)算元素的布局信息
4.對(duì)布局樹進(jìn)行分層,并計(jì)算元素的布局信息
5.為每個(gè)圖層生成繪制列表殉摔、并將其提交到合成線程
6.合成線程將圖層分成圖塊州胳,并在光柵線程池中將圖塊轉(zhuǎn)成位圖
7.合成線程發(fā)送繪制圖塊命令DrawQuad給瀏覽器進(jìn)程
8.瀏覽器進(jìn)程根據(jù)DrawQuad消息生成頁面,并顯示到顯示器上
image.png
HTML解析
HTML Parser的任務(wù)是將HTML標(biāo)記解析成DOM Tree逸月,舉個(gè)例子
舉個(gè)例子:一段HTML
<html>
<head>
<title>Web page parsing</title>
</head>
<body>
<div>
<h1>Web page parsing</h1>
<p>This is an example Web page.</p>
</div>
</body>
</html>
經(jīng)過解析之后的DOM Tree差不多就是
將文本的HTML文檔栓撞,提煉出關(guān)鍵信息,嵌套層級(jí)的樹形結(jié)構(gòu)彻采,便于計(jì)算拓展腐缤。這就是HTML Parser的作用。
CSS解析
CSS Parser將CSS解析成Style Rules肛响,Style Rules也叫CSSOM(CSS Object Model)岭粤。
StyleRules也是一個(gè)樹形結(jié)構(gòu),根據(jù)CSS文件整理出來的類似DOM Tree的樹形結(jié)構(gòu):
與HTML Parser相似特笋,CSS Parser作用就是將很多個(gè)CSS文件中的樣式合并解析出具有樹形結(jié)構(gòu)Style Rules剃浇。
JavaScript解析
瀏覽器解析文檔,當(dāng)遇到<script>標(biāo)簽的時(shí)候猎物,會(huì)立即解析腳本虎囚,停止解析文檔(因?yàn)镴S可能會(huì)改動(dòng)DOM和CSS,所以繼續(xù)解析會(huì)造成浪費(fèi))蔫磨。
如果腳本是外部的淘讥,會(huì)等待腳本下載完畢,再繼續(xù)解析文檔〉倘纾現(xiàn)在可以在script標(biāo)簽上增加屬性 defer或者async蒲列。
腳本解析會(huì)將腳本中改變DOM和CSS的地方分別解析出來窒朋,追加到DOM Tree和Style Rules上。
呈現(xiàn)樹(Render Tree)
Render Tree的構(gòu)建其實(shí)就是DOM Tree和CSSOM Attach的過程蝗岖。
呈現(xiàn)器是和 DOM 元素相對(duì)應(yīng)的侥猩,但并非一一對(duì)應(yīng)。Render Tree實(shí)際上就是一個(gè)計(jì)算好樣式抵赢,與HTML對(duì)應(yīng)的(包括哪些顯示欺劳,那些不顯示)的Tree。
布局Layout
創(chuàng)建渲染樹后铅鲤,下一步就是布局(Layout),或者叫回流(reflow,relayout)划提,這個(gè)過程就是通過渲染樹中渲染對(duì)象的信息,計(jì)算出每一個(gè)渲染對(duì)象的位置和尺寸邢享,將其安置在瀏覽器窗口的正確位置腔剂,而有些時(shí)候我們會(huì)在文檔布局完成后對(duì)DOM進(jìn)行修改,這時(shí)候可能需要重新進(jìn)行布局驼仪,也可稱其為回流掸犬,本質(zhì)上還是一個(gè)布局的過程,每一個(gè)渲染對(duì)象都有一個(gè)布局或者回流方法绪爸,實(shí)現(xiàn)其布局或回流湾碎。
對(duì)渲染樹的布局可以分為全局和局部的,全局即對(duì)整個(gè)渲染樹進(jìn)行重新布局奠货,如當(dāng)我們改變了窗口尺寸或方向或者是修改了根元素的尺寸或者字體大小等介褥;而局部布局可以是對(duì)渲染樹的某部分或某一個(gè)渲染對(duì)象進(jìn)行重新布局。
繪制(Painting)
1.在繪制階段递惋,系統(tǒng)會(huì)遍歷呈現(xiàn)樹柔滔,會(huì)把一個(gè)圖層的繪制拆分成很多小的繪制指令,然后再把這些指令按照順序組成一個(gè)待繪制列表萍虽。
繪制列表只是用來記錄繪制順序和繪制指令的列表睛廊,而實(shí)際上繪制操作是有渲染引擎中的合成線程來完成的。
當(dāng)圖層的繪制列表準(zhǔn)備好之后杉编,主線程會(huì)把該繪制列表提交(commit)給合成線程超全。
然后合成線程會(huì)按照視口附近的圖塊來優(yōu)先生成位圖,實(shí)際生成位圖塊來優(yōu)先生成位圖邓馒,實(shí)際生成位圖的操作是由柵格化來執(zhí)行的嘶朱。所謂的柵格化,是指圖塊轉(zhuǎn)換為位圖光酣。運(yùn)行方式如下圖所示:
通常疏遏,柵格化過程都會(huì)使用 GPU 來加速生成,使用 GPU 來加速生成,使用 GPU 生成位圖的過程叫快速柵格化财异,或者GPU 柵格化下翎,生成的位圖被保存在 GPU 內(nèi)存中。
GPU 操作是運(yùn)行在 GPU 進(jìn)程中宝当,如果柵格化操作使用了 GPU,那么最終生成位圖的操作是在 GPU 中完成的胆萧,這就涉及到了跨進(jìn)程操作庆揩。如下圖所示:
最終一旦所有圖塊都被光柵化,合成線程就會(huì)生成一個(gè)繪制圖塊的命令——“DrawQuad”跌穗,然后將該命令提交給瀏覽器進(jìn)程订晌,最后通過合成線程的DrawQuad命令,將其頁面內(nèi)容繪制到內(nèi)存中蚌吸,最后在將內(nèi)存顯示在屏幕上锈拨。
關(guān)于介紹網(wǎng)絡(luò)傳輸性能優(yōu)化這項(xiàng)工作之前,我們需要了解瀏覽器處理用戶請(qǐng)求的過程羹唠,如下圖:
關(guān)于如何在渲染過程中進(jìn)行網(wǎng)站性能優(yōu)化實(shí)戰(zhàn)奕枢,請(qǐng)參考https://juejin.im/post/5b6fa8c86fb9a0099910ac91
參考鏈接
https://segmentfault.com/a/1190000010298038#articleHeader8
https://time.geekbang.org/column/article/118826