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