url上接收到 el表达式 不渲染_一文摸透从输入URL到页面渲染的过程
一文摸透從輸入U(xiǎn)RL到頁(yè)面渲染的過(guò)程
從輸入U(xiǎn)RL到頁(yè)面渲染需要Chrome瀏覽器的多個(gè)進(jìn)程配合,所以我們先來(lái)談?wù)劕F(xiàn)階段Chrome瀏覽器的多進(jìn)程架構(gòu)。
一、Chrome架構(gòu)
目前Chrome采用的是多進(jìn)程的架構(gòu)模式,可分為主要的五類(lèi)進(jìn)程,分別是:瀏覽器(Browser)主進(jìn)程、 GPU 進(jìn)程、網(wǎng)絡(luò)(NetWork)進(jìn)程、多個(gè)渲染進(jìn)程和多個(gè)插件進(jìn)程;
- 瀏覽器進(jìn)程。主要負(fù)責(zé)界面顯示、用戶(hù)交互、子進(jìn)程管理,同時(shí)提供存儲(chǔ)等功能。
- 渲染進(jìn)程。核心任務(wù)是將HTML、CSS 和 JavaScript轉(zhuǎn)換為用戶(hù)可以與之交互的網(wǎng)頁(yè),排版引擎Blink和JavaScript引擎V8都是運(yùn)行在該進(jìn)程中,默認(rèn)情況下,Chrome會(huì)為每個(gè)Tab標(biāo)簽創(chuàng)建一個(gè)渲染進(jìn)程。出于安全考慮,渲染進(jìn)程都是運(yùn)行在沙箱模式下。
- GPU進(jìn)程。其實(shí),Chrome剛開(kāi)始發(fā)布的時(shí)候是沒(méi)有GPU進(jìn)程的。而GPU的使用初衷是為了實(shí)現(xiàn)3D CSS的效果,只是隨后網(wǎng)頁(yè)、Chrome的UI界面都選擇采用GPU來(lái)繪制,這使得GPU成為瀏覽器普遍的需求。最后,Chrome在其多進(jìn)程架構(gòu)上也引入了GPU進(jìn)程。
- 網(wǎng)絡(luò)進(jìn)程。主要負(fù)責(zé)頁(yè)面的網(wǎng)絡(luò)資源加載,之前是作為一個(gè)模塊運(yùn)行在瀏覽器進(jìn)程里面的,直至最近才獨(dú)立出來(lái),成為一個(gè)單獨(dú)的進(jìn)程。
- 插件進(jìn)程。主要是負(fù)責(zé)插件的運(yùn)行,因插件易崩潰,所以需要通過(guò)插件進(jìn)程來(lái)隔離,以保證插件進(jìn)程崩潰不會(huì)對(duì)瀏覽器和頁(yè)面造成影響
了解了Chrome的多進(jìn)程架構(gòu),就能夠從宏觀上理解從輸入U(xiǎn)RL到頁(yè)面渲染的過(guò)程了,這個(gè)過(guò)程主要分為導(dǎo)航階段和渲染階段。
二、導(dǎo)航階段
Ⅰ.瀏覽器主進(jìn)程
1.用戶(hù)輸入U(xiǎn)RL
- **1、**瀏覽器進(jìn)程檢查url,組裝協(xié)議,構(gòu)成完整的url,這時(shí)候有兩種情況: 輸入的是搜索內(nèi)容:地址欄會(huì)使用瀏覽器默認(rèn)的搜索引擎,來(lái)合成新的帶搜索關(guān)鍵字的URL。 輸入的是請(qǐng)求URL:地址欄會(huì)根據(jù)規(guī)則,給這段內(nèi)容加上協(xié)議,合成為完整的URL;
- **2、**瀏覽器進(jìn)程通過(guò)進(jìn)程間通信(IPC)把url請(qǐng)求發(fā)送給網(wǎng)絡(luò)進(jìn)程;
Ⅱ.網(wǎng)絡(luò)進(jìn)程
2.URL請(qǐng)求過(guò)程
- **3、**網(wǎng)絡(luò)進(jìn)程接收到url請(qǐng)求后檢查本地緩存是否緩存了該請(qǐng)求資源,如果有則將該資源返回給瀏覽器進(jìn)程;
這里涉及到瀏覽器的緩存策略問(wèn)題,有興趣的可以上網(wǎng)查閱相關(guān)資料。
- **4、**準(zhǔn)備IP地址和端口:進(jìn)行DNS解析時(shí)先查找緩存,沒(méi)有再使用DNS服務(wù)器解析,查找順序?yàn)?#xff1a; 瀏覽器緩存; 本機(jī)緩存; hosts文件; 路由器緩存; ISP DNS緩存; DNS遞歸查詢(xún)(本地DNS服務(wù)器 -> 權(quán)限D(zhuǎn)NS服務(wù)器 -> 頂級(jí)DNS服務(wù)器 -> 13臺(tái)根DNS服務(wù)器)
- **5、**等待TCP隊(duì)列:瀏覽器會(huì)為每個(gè)域名最多維護(hù)6個(gè)TCP連接,如果發(fā)起一個(gè)HTTP請(qǐng)求時(shí),這 6個(gè) TCP連接都處于忙碌狀態(tài),那么這個(gè)請(qǐng)求就會(huì)處于排隊(duì)狀態(tài);解決方案: 采用域名分片技術(shù):將一個(gè)站點(diǎn)的資源放在多個(gè)(CDN)域名下面。 升級(jí)為HTTP2,就沒(méi)有6個(gè)TCP連接的限制了;
- **6、**通過(guò)三次握手建立TCP連接: **第一次:**客戶(hù)端先向服務(wù)器端發(fā)送一個(gè)同步數(shù)據(jù)包,報(bào)文的TCP首部中:標(biāo)志位:**同步SYN**為1,表示這是一個(gè)請(qǐng)求建立連接的數(shù)據(jù)包;序號(hào)Seq=x,x為所傳送數(shù)據(jù)的第一個(gè)字節(jié)的序號(hào),隨后進(jìn)入SYN-SENT狀態(tài); 標(biāo)志位值為1表示該標(biāo)志位有效。 **第二次:**服務(wù)器根據(jù)收到數(shù)據(jù)包的SYN標(biāo)志位判斷為建立連接的請(qǐng)求,隨后返回一個(gè)確認(rèn)數(shù)據(jù)包,其中標(biāo)志位SYN=1,ACK=1,序號(hào)seq=y,確認(rèn)號(hào)ack=x + 1表示收到了客戶(hù)端傳輸過(guò)來(lái)的x字節(jié)數(shù)據(jù),并希望下次從x+1個(gè)字節(jié)開(kāi)始傳,并進(jìn)入SYN-RCVD狀態(tài); 這里要區(qū)分標(biāo)志位ACK和確認(rèn)號(hào)ack; **第三次:**客戶(hù)端收到后,再給服務(wù)器發(fā)送一個(gè)確認(rèn)數(shù)據(jù)包,標(biāo)志位ACK=1,序號(hào)seq=x+1,確認(rèn)號(hào)ack=y+1,隨后進(jìn)入ESTABLISHED狀態(tài); 服務(wù)器端收到后,也進(jìn)入ESTABLISHED狀態(tài),由此成功建立了TCP連接,可以開(kāi)始數(shù)據(jù)傳送; 為什么要第三次揮手?避免服務(wù)器等待造成資源浪費(fèi),具體原因: 如果沒(méi)有最后一個(gè)數(shù)據(jù)包確認(rèn)(第三次握手),A先發(fā)出一個(gè)建立連接的請(qǐng)求數(shù)據(jù)包,由于網(wǎng)絡(luò)原因繞遠(yuǎn)路了。A經(jīng)過(guò)設(shè)定的超時(shí)時(shí)間后還未收到B的確認(rèn)數(shù)據(jù)包。 于是發(fā)出第二個(gè)建立連接的請(qǐng)求數(shù)據(jù)包,這次網(wǎng)路通暢,B的確認(rèn)數(shù)據(jù)包也很快就到達(dá)A。于是A與B開(kāi)始傳輸數(shù)據(jù); 過(guò)了一會(huì)A第一次發(fā)出的建立連接的請(qǐng)求數(shù)據(jù)包到達(dá)了B,B以為是再次建立連接,所以又發(fā)出一個(gè)確認(rèn)數(shù)據(jù)包。由于A已經(jīng)收到了一個(gè)確認(rèn)數(shù)據(jù)包,所以會(huì)忽略B發(fā)來(lái)的第二個(gè)確認(rèn)數(shù)據(jù)包,但是B發(fā)出確認(rèn)數(shù)據(jù)包之后就要一直等待A的回復(fù),而A永遠(yuǎn)也不會(huì)回復(fù)。 由此造成服務(wù)器資源浪費(fèi),這種情況多了B計(jì)算機(jī)可能就停止響應(yīng)了。
- **7、**構(gòu)建并發(fā)送HTTP請(qǐng)求信息;
- **8、**服務(wù)器端處理請(qǐng)求;
- **9、**客戶(hù)端處理響應(yīng),首先檢查服務(wù)器響應(yīng)報(bào)文的狀態(tài)碼: 如果是301/302表示服務(wù)器已更換域名需要重定向,這時(shí)網(wǎng)絡(luò)進(jìn)程會(huì)從響應(yīng)頭的Location字段里面讀取重定向的地址,然后再發(fā)起新的HTTP或者HTTPS請(qǐng)求,跳回第4步。 如果是200,就檢查Content-Type字段,值為text/html說(shuō)明是HTML文檔,是application/octet-stream說(shuō)明是文件下載;
- **10、**請(qǐng)求結(jié)束,當(dāng)通用首部字段Conection不是Keep-Alive時(shí),即不為T(mén)CP長(zhǎng)連接時(shí),通過(guò)四次揮手?jǐn)嚅_(kāi)TCP連接:
- **第一次:**客戶(hù)端(主動(dòng)斷開(kāi)連接)發(fā)送數(shù)據(jù)包給服務(wù)器,其中標(biāo)志位FIN=1,序號(hào)位seq=u,并停止發(fā)送數(shù)據(jù);
- **第二次:**服務(wù)器收到數(shù)據(jù)包后,由于還需傳輸數(shù)據(jù),無(wú)法立即關(guān)閉連接,先返回一個(gè)標(biāo)志位ACK=1,序號(hào)seq=v,確認(rèn)號(hào)ack=u+1的數(shù)據(jù)包;
- **第三次:**服務(wù)器準(zhǔn)備好斷開(kāi)連接后,返回一個(gè)數(shù)據(jù)包,其中標(biāo)志位FIN=1,標(biāo)志位ACK=1,序號(hào)seq=w,確認(rèn)號(hào)ack=u+1;
- **第四次:**客戶(hù)端收到數(shù)據(jù)包后,返回一個(gè)標(biāo)志位ACK=1,序號(hào)seq=u+1,確認(rèn)號(hào)ack=w+1的數(shù)據(jù)包。
由此通過(guò)四次揮手?jǐn)嚅_(kāi)TCP連接。
詳細(xì)過(guò)程參見(jiàn):詳解TCP連接的“三次握手”與“四次揮手”(上)
- **為什么要四次揮手?**由于服務(wù)器不能馬上斷開(kāi)連接,導(dǎo)致FIN釋放連接報(bào)文與ACK確認(rèn)接收?qǐng)?bào)文需要分兩次傳輸,即第二次和第三次"揮手";
3.準(zhǔn)備渲染進(jìn)程
- **11、**準(zhǔn)備渲染進(jìn)程:瀏覽器進(jìn)程檢查當(dāng)前url是否與之前打開(kāi)了渲染進(jìn)程的頁(yè)面的根域名相同,如果相同,則復(fù)用原來(lái)的進(jìn)程,如果不同,則開(kāi)啟新的渲染進(jìn)程;
4.提交文檔
- **12、**提交文檔: 渲染進(jìn)程準(zhǔn)備好后,瀏覽器向渲染進(jìn)程發(fā)起“提交文檔”的消息,渲染進(jìn)程接收到消息后與網(wǎng)絡(luò)進(jìn)程建立傳輸數(shù)據(jù)的“管道” 渲染進(jìn)程接收完數(shù)據(jù)后,向?yàn)g覽器發(fā)送“確認(rèn)提交” 瀏覽器進(jìn)程接收到確認(rèn)消息后更新瀏覽器界面狀態(tài):安全狀態(tài)、地址欄url、前進(jìn)后退的歷史狀態(tài)、更新web頁(yè)面
三、渲染階段
在渲染階段通過(guò)渲染流水線在渲染進(jìn)程的主線程和合成線程配合下,完成頁(yè)面的渲染;
Ⅲ.渲染進(jìn)程
渲染進(jìn)程中的主線程部分
5.構(gòu)建DOM樹(shù)
- 13、先將請(qǐng)求回來(lái)的數(shù)據(jù)解壓,隨后HTML解析器將其中的HTML字節(jié)流通過(guò)分詞器拆分為一個(gè)個(gè)Token,然后生成節(jié)點(diǎn)Node,最后解析成瀏覽器識(shí)別的DOM樹(shù)結(jié)構(gòu)。 可以通過(guò)Chrome調(diào)試工具的Console選項(xiàng)打開(kāi)控制臺(tái)輸入document查看DOM樹(shù);
渲染引擎還有一個(gè)安全檢查模塊叫 XSSAuditor,是用來(lái)檢測(cè)詞法安全的。在分詞器解析出來(lái) Token 之后,它會(huì)檢測(cè)這些模塊是否安全,比如是否引用了外部腳本,是否符合 CSP 規(guī)范,是否存在跨站點(diǎn)請(qǐng)求等。如果出現(xiàn)不符合規(guī)范的內(nèi)容,XSSAuditor 會(huì)對(duì)該腳本或者下載任務(wù)進(jìn)行攔截。
首次解析HTML時(shí)渲染進(jìn)程會(huì)開(kāi)啟一個(gè)預(yù)解析線程,遇到HTML文檔中內(nèi)嵌的JavaScript和CSS外部引用就會(huì)同步提前下載這些文件,下載時(shí)間以最后下載完的文件為準(zhǔn)。
6.構(gòu)建CSSOM
- 14、CSS解析器將CSS轉(zhuǎn)換為瀏覽器能識(shí)別的styleSheets也就是CSSOM:可以通過(guò)控制臺(tái)輸入document.styleSheets查看; 這里要考慮一下阻塞的問(wèn)題,由于JavaScript有修改CSS和HTML的能力,所以,需要先等到 CSS 文件下載完成并生成 CSSOM,然后再執(zhí)行 JavaScript 腳本,最后再繼續(xù)構(gòu)建 DOM。由于這種阻塞,導(dǎo)致了解析白屏;
優(yōu)化方案:
移除js和css的文件下載:通過(guò)內(nèi)聯(lián) JavaScript、內(nèi)聯(lián) CSS; 盡量減少文件大小:如通過(guò) webpack 等工具移除不必要的注釋,并壓縮 js 文件; 將不進(jìn)行DOM操作或CSS樣式修改的 JavaScript 標(biāo)記上 sync 或者 defer異步引入; 使用媒體查詢(xún)屬性:將大的CSS文件拆分成多個(gè)不同用途的 CSS 文件,只有在特定的場(chǎng)景下才會(huì)加載特定的 CSS 文件。
可以通過(guò)瀏覽器調(diào)試工具的Network面板中的DOMContentLoaded查看最后生成DOM樹(shù)所需的時(shí)間;
7.樣式計(jì)算
- **15、**轉(zhuǎn)換樣式表中的屬性值,使其標(biāo)準(zhǔn)化。比如將em轉(zhuǎn)換為px,color轉(zhuǎn)換為rgb;
- **16、**計(jì)算DOM樹(shù)中每個(gè)節(jié)點(diǎn)的具體樣式,這里遵循CSS的繼承和層疊規(guī)則;可以通過(guò)Chrome調(diào)試工具的Elements選項(xiàng)的Computed查看某一標(biāo)簽的最終樣式;
8.布局階段
- **17、**創(chuàng)建布局樹(shù),遍歷DOM樹(shù)中的所有節(jié)點(diǎn),去掉所有隱藏的節(jié)點(diǎn)(比如head,添加了display:none的節(jié)點(diǎn)),只在布局樹(shù)中保留可見(jiàn)的節(jié)點(diǎn)。
- **18、**計(jì)算布局樹(shù)中節(jié)點(diǎn)的坐標(biāo)位置(較復(fù)雜,這里不展開(kāi));
9.分層
- **19、**對(duì)布局樹(shù)進(jìn)行分層,并生成分層樹(shù)(Layer Tree),可以通過(guò)Chrome調(diào)試工具的Layer選項(xiàng)查看。分層樹(shù)中每一個(gè)節(jié)點(diǎn)都直接或間接的屬于一個(gè)圖層(如果一個(gè)節(jié)點(diǎn)沒(méi)有對(duì)應(yīng)的層,那么這個(gè)節(jié)點(diǎn)就從屬于父節(jié)點(diǎn)的圖層)
10.圖層繪制
- **20、**為每個(gè)圖層生成繪制列表(即繪制指令),并將其提交到合成線程。以上操作都是在渲染進(jìn)程中的主線程中進(jìn)行的,提交到合成線程后就不阻塞主線程了;
渲染進(jìn)程中的合成線程部分
11.切分圖塊
21、合成線程將圖層切分成大小固定的圖塊(256x256或者512x512)然后優(yōu)先繪制靠近視口的圖塊,這樣就可以大大加速頁(yè)面的顯示速度;
Ⅳ.GPU進(jìn)程
12.柵格化操作
- 22、在光柵化線程池中將圖塊轉(zhuǎn)換成位圖,通常這個(gè)過(guò)程都會(huì)使用GPU來(lái)加速生成,使用GPU生成位圖的過(guò)程叫快速柵格化,或者GPU柵格化,生成的位圖被保存在GPU內(nèi)存中。
Ⅴ.瀏覽器主進(jìn)程
13.合成與顯示
- **23、**合成:一旦所有圖塊都被光柵化,合成線程就會(huì)將它們合成為一張圖片,并生成一個(gè)繪制圖塊的命令——“DrawQuad”,然后將該命令提交給瀏覽器進(jìn)程。
注意了:合成的過(guò)程是在渲染進(jìn)程的合成線程中完成的,不會(huì)影響到渲染進(jìn)程的主線程執(zhí)行;
- **24、**顯示:瀏覽器進(jìn)程里面有一個(gè)叫viz的組件,用來(lái)接收合成線程發(fā)過(guò)來(lái)的DrawQuad命令,然后根據(jù)DrawQuad命令,將其頁(yè)面內(nèi)容繪制到內(nèi)存中,最后再將內(nèi)存顯示在屏幕上。
到這里,經(jīng)過(guò)這一系列的階段,編寫(xiě)好的HTML、CSS、JavaScript等文件,經(jīng)過(guò)瀏覽器就會(huì)顯示出漂亮的頁(yè)面了。
作者:AhuntSun
鏈接:https://juejin.im/post/5e8be3f2f265da47d12914fc
來(lái)源:掘金
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。
總結(jié)
以上是生活随笔為你收集整理的url上接收到 el表达式 不渲染_一文摸透从输入URL到页面渲染的过程的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: requests下载大文件_11种方法教
- 下一篇: Mac上Genymotion模拟器无法联