<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          一文摸透從輸入URL到頁面渲染的過程

          共 4697字,需瀏覽 10分鐘

           ·

          2020-08-27 09:49

          來源 |?https://www.cnblogs.com/AhuntSun-blog/p/12641050.html
          從輸入URL到頁面渲染需要Chrome瀏覽器的多個進(jìn)程配合,所以我們先來談?wù)劕F(xiàn)階段Chrome瀏覽器的多進(jìn)程架構(gòu)。

          一、Chrome架構(gòu)

          目前Chrome采用的是多進(jìn)程的架構(gòu)模式,可分為主要的五類進(jìn)程,分別是:瀏覽器(Browser)主進(jìn)程、 GPU 進(jìn)程、網(wǎng)絡(luò)(NetWork)進(jìn)程、多個渲染進(jìn)程和多個插件進(jìn)程;
          • 瀏覽器進(jìn)程。主要負(fù)責(zé)界面顯示、用戶交互、子進(jìn)程管理,同時提供存儲等功能。
          • 渲染進(jìn)程。核心任務(wù)是將 HTML、CSS 和 JavaScript 轉(zhuǎn)換為用戶可以與之交互的網(wǎng)頁,排版引擎Blink和JavaScript引擎V8都是運行在該進(jìn)程中,默認(rèn)情況下,Chrome會為每個Tab標(biāo)簽創(chuàng)建一個渲染進(jìn)程。出于安全考慮,渲染進(jìn)程都是運行在沙箱模式下。
          • GPU進(jìn)程。其實,Chrome剛開始發(fā)布的時候是沒有GPU進(jìn)程的。而GPU的使用初衷是為了實現(xiàn)3D CSS的效果,只是隨后網(wǎng)頁、Chrome的UI界面都選擇采用GPU來繪制,這使得GPU成為瀏覽器普遍的需求。最后,Chrome在其多進(jìn)程架構(gòu)上也引入了GPU進(jìn)程。
          • 網(wǎng)絡(luò)進(jìn)程。主要負(fù)責(zé)頁面的網(wǎng)絡(luò)資源加載,之前是作為一個模塊運行在瀏覽器進(jìn)程里面的,直至最近才獨立出來,成為一個單獨的進(jìn)程。
          • 插件進(jìn)程。主要是負(fù)責(zé)插件的運行,因插件易崩潰,所以需要通過插件進(jìn)程來隔離,以保證插件進(jìn)程崩潰不會對瀏覽器和頁面造成影響
          了解了Chrome的多進(jìn)程架構(gòu),就能夠從宏觀上理解從輸入URL到頁面渲染的過程了,這個過程主要分為導(dǎo)航階段和渲染階段。

          二、導(dǎo)航階段

          Ⅰ.瀏覽器主進(jìn)程

          1.用戶輸入URL

          • 1、瀏覽器進(jìn)程檢查url,組裝協(xié)議,構(gòu)成完整的url,這時候有兩種情況:
            • 輸入的是搜索內(nèi)容:地址欄會使用瀏覽器默認(rèn)的搜索引擎,來合成新的帶搜索關(guān)鍵字的URL。
            • 輸入的是請求URL:地址欄會根據(jù)規(guī)則,給這段內(nèi)容加上協(xié)議,合成為完整的URL;
          • 2、瀏覽器進(jìn)程通過進(jìn)程間通信(IPC)把url請求發(fā)送給網(wǎng)絡(luò)進(jìn)程;

          Ⅱ.網(wǎng)絡(luò)進(jìn)程

          2.URL請求過程

          • 3、網(wǎng)絡(luò)進(jìn)程接收到url請求后檢查本地緩存是否緩存了該請求資源,如果有則將該資源返回給瀏覽器進(jìn)程;
          這里涉及到瀏覽器與HTTP協(xié)議的緩存策略問題,有興趣的可以看這篇文章:詳解HTTP協(xié)議
          • 4、準(zhǔn)備IP地址和端口:進(jìn)行DNS解析時先查找緩存,沒有再使用DNS服務(wù)器解析,查找順序為:
            • 瀏覽器緩存;
            • 本機(jī)緩存;
            • hosts文件;
            • 路由器緩存;
            • ISP DNS緩存;
            • DNS遞歸查詢(本地DNS服務(wù)器 -> 權(quán)限D(zhuǎn)NS服務(wù)器 -> 頂級DNS服務(wù)器 ->?13臺根DNS服務(wù)器)
          • 5、等待TCP隊列:瀏覽器會為每個域名最多維護(hù)6個TCP連接,如果發(fā)起一個HTTP請求時,這 6個 TCP連接都處于忙碌狀態(tài),那么這個請求就會處于排隊狀態(tài);解決方案:
          • 采用域名分片技術(shù):將一個站點的資源放在多個(CDN)域名下面。
            升級為HTTP2,就沒有6個TCP連接的限制了;
            6、通過三次握手建立TCP連接:
            標(biāo)志位值為1表示該標(biāo)志位有效。
            這里要區(qū)分標(biāo)志位ACK和確認(rèn)號ack;
            服務(wù)器端收到后,也進(jìn)入ESTABLISHED狀態(tài),由此成功建立了TCP連接,可以開始數(shù)據(jù)傳送;
            如果沒有最后一個數(shù)據(jù)包確認(rèn)(第三次握手),A先發(fā)出一個建立連接的請求數(shù)據(jù)包,由于網(wǎng)絡(luò)原因繞遠(yuǎn)路了。A經(jīng)過設(shè)定的超時時間后還未收到B的確認(rèn)數(shù)據(jù)包。
            于是發(fā)出第二個建立連接的請求數(shù)據(jù)包,這次網(wǎng)路通暢,B的確認(rèn)數(shù)據(jù)包也很快就到達(dá)A。于是A與B開始傳輸數(shù)據(jù);
            過了一會A第一次發(fā)出的建立連接的請求數(shù)據(jù)包到達(dá)了B,B以為是再次建立連接,所以又發(fā)出一個確認(rèn)數(shù)據(jù)包。由于A已經(jīng)收到了一個確認(rèn)數(shù)據(jù)包,所以會忽略B發(fā)來的第二個確認(rèn)數(shù)據(jù)包,但是B發(fā)出確認(rèn)數(shù)據(jù)包之后就要一直等待A的回復(fù),而A永遠(yuǎn)也不會回復(fù)。
            由此造成服務(wù)器資源浪費,這種情況多了B計算機(jī)可能就停止響應(yīng)了。
            • 為什么要第三次揮手?避免服務(wù)器等待造成資源浪費,具體原因:
            • 第三次:客戶端收到后,再給服務(wù)器發(fā)送一個確認(rèn)數(shù)據(jù)包,標(biāo)志位ACK=1,序號seq=x+1,確認(rèn)號ack=y+1,隨后進(jìn)入ESTABLISHED狀態(tài);
            • 第二次:服務(wù)器根據(jù)收到數(shù)據(jù)包的SYN標(biāo)志位判斷為建立連接的請求,隨后返回一個確認(rèn)數(shù)據(jù)包,其中標(biāo)志位SYN=1,ACK=1,序號seq=y,確認(rèn)號ack=x + 1表示收到了客戶端傳輸過來的x字節(jié)數(shù)據(jù),并希望下次從x+1個字節(jié)開始傳,并進(jìn)入SYN-RCVD狀態(tài);
            • 第一次:客戶端先向服務(wù)器端發(fā)送一個同步數(shù)據(jù)包,報文的TCP首部中:標(biāo)志位:同步SYN為1,表示這是一個請求建立連接的數(shù)據(jù)包;序號Seq=x,x為所傳送數(shù)據(jù)的第一個字節(jié)的序號,隨后進(jìn)入SYN-SENT狀態(tài);
          • 7、構(gòu)建并發(fā)送HTTP請求信息;
          • 8、服務(wù)器端處理請求;
          • 9、客戶端處理響應(yīng),首先檢查服務(wù)器響應(yīng)報文的狀態(tài)碼:
            • 如果是301/302表示服務(wù)器已更換域名需要重定向,這時網(wǎng)絡(luò)進(jìn)程會從響應(yīng)頭的Location字段里面讀取重定向的地址,然后再發(fā)起新的HTTP或者HTTPS請求,跳回第4步。
            • 如果是200,就檢查Content-Type字段,值為text/html說明是HTML文檔,是application/octet-stream說明是文件下載;
          • 10、請求結(jié)束,當(dāng)通用首部字段Conection不是Keep-Alive時,即不為TCP長連接時,通過四次揮手?jǐn)嚅_TCP連接:
          • 第一次:客戶端(主動斷開連接)發(fā)送數(shù)據(jù)包給服務(wù)器,其中標(biāo)志位FIN=1,序號位seq=u,并停止發(fā)送數(shù)據(jù);
          • 第二次:服務(wù)器收到數(shù)據(jù)包后,由于還需傳輸數(shù)據(jù),無法立即關(guān)閉連接,先返回一個標(biāo)志位ACK=1,序號seq=v,確認(rèn)號ack=u+1的數(shù)據(jù)包;
          • 第三次:服務(wù)器準(zhǔn)備好斷開連接后,返回一個數(shù)據(jù)包,其中標(biāo)志位FIN=1,標(biāo)志位ACK=1,序號seq=w,確認(rèn)號ack=u+1;
          • 第四次:客戶端收到數(shù)據(jù)包后,返回一個標(biāo)志位ACK=1,序號seq=u+1,確認(rèn)號ack=w+1的數(shù)據(jù)包。
          由此通過四次揮手?jǐn)嚅_TCP連接。
          詳細(xì)過程參見:詳解TCP連接的“三次握手”與“四次揮手”(上)
          • 為什么要四次揮手?由于服務(wù)器不能馬上斷開連接,導(dǎo)致FIN釋放連接報文與ACK確認(rèn)接收報文需要分兩次傳輸,即第二次和第三次"揮手";

          3.準(zhǔn)備渲染進(jìn)程

          • 11、準(zhǔn)備渲染進(jìn)程:瀏覽器進(jìn)程檢查當(dāng)前url是否與之前打開了渲染進(jìn)程的頁面的根域名相同,如果相同,則復(fù)用原來的進(jìn)程,如果不同,則開啟新的渲染進(jìn)程;

          4.提交文檔

          • 12、提交文檔:
            • 渲染進(jìn)程準(zhǔn)備好后,瀏覽器向渲染進(jìn)程發(fā)起“提交文檔”的消息,渲染進(jìn)程接收到消息后與網(wǎng)絡(luò)進(jìn)程建立傳輸數(shù)據(jù)的“管道”
            • 渲染進(jìn)程接收完數(shù)據(jù)后,向瀏覽器發(fā)送“確認(rèn)提交”
            • 瀏覽器進(jìn)程接收到確認(rèn)消息后更新瀏覽器界面狀態(tài):安全狀態(tài)、地址欄url、前進(jìn)后退的歷史狀態(tài)、更新web頁面

          三、渲染階段

          在渲染階段通過渲染流水線在渲染進(jìn)程的主線程和合成線程配合下,完成頁面的渲染;

          Ⅲ.渲染進(jìn)程

          渲染進(jìn)程中的主線程部分

          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ù)進(jìn)行攔截。
          首次解析HTML時渲染進(jìn)程會開啟一個預(yù)解析線程,遇到HTML文檔中內(nèi)嵌的JavaScript和CSS外部引用就會同步提前下載這些文件,下載時間以最后下載完的文件為準(zhǔn)。

          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 文件;
          • 將不進(jìn)行DOM操作或CSS樣式修改的 JavaScript 標(biāo)記上 sync 或者 defer異步引入;
          • 使用媒體查詢屬性:將大的CSS文件拆分成多個不同用途的 CSS 文件,只有在特定的場景下才會加載特定的 CSS 文件。
          可以通過瀏覽器調(diào)試工具的Network面板中的DOMContentLoaded查看最后生成DOM樹所需的時間;

          7.樣式計算

          • 15、轉(zhuǎn)換樣式表中的屬性值,使其標(biāo)準(zhǔn)化。比如將em轉(zhuǎn)換為px,color轉(zhuǎn)換為rgb;
          • 16、計算DOM樹中每個節(jié)點的具體樣式,這里遵循CSS的繼承和層疊規(guī)則;可以通過Chrome調(diào)試工具的Elements選項的Computed查看某一標(biāo)簽的最終樣式;

          8.布局階段

          • 17、創(chuàng)建布局樹,遍歷DOM樹中的所有節(jié)點,去掉所有隱藏的節(jié)點(比如head,添加了display:none的節(jié)點),只在布局樹中保留可見的節(jié)點。
          • 18、計算布局樹中節(jié)點的坐標(biāo)位置(較復(fù)雜,這里不展開);

          9.分層

          • 19、對布局樹進(jìn)行分層,并生成分層樹(Layer Tree),可以通過Chrome調(diào)試工具的Layer選項查看。分層樹中每一個節(jié)點都直接或間接的屬于一個圖層(如果一個節(jié)點沒有對應(yīng)的層,那么這個節(jié)點就從屬于父節(jié)點的圖層)

          10.圖層繪制

          • 20、為每個圖層生成繪制列表(即繪制指令),并將其提交到合成線程。以上操作都是在渲染進(jìn)程中的主線程中進(jìn)行的,提交到合成線程后就不阻塞主線程了;
          渲染進(jìn)程中的合成線程部分

          11.切分圖塊

          21、合成線程將圖層切分成大小固定的圖塊(256x256或者512x512)然后優(yōu)先繪制靠近視口的圖塊,這樣就可以大大加速頁面的顯示速度;

          Ⅳ.GPU進(jìn)程

          12.柵格化操作

          • 22、在光柵化線程池中將圖塊轉(zhuǎn)換成位圖,通常這個過程都會使用GPU來加速生成,使用GPU生成位圖的過程叫快速柵格化,或者GPU柵格化,生成的位圖被保存在GPU內(nèi)存中。

          Ⅴ.瀏覽器主進(jìn)程

          13.合成與顯示

          • 23、合成:一旦所有圖塊都被光柵化,合成線程就會將它們合成為一張圖片,并生成一個繪制圖塊的命令——“DrawQuad”,然后將該命令提交給瀏覽器進(jìn)程。
          注意了:合成的過程是在渲染進(jìn)程的合成線程中完成的,不會影響到渲染進(jìn)程的主線程執(zhí)行;
          • 24、顯示:瀏覽器進(jìn)程里面有一個叫viz的組件,用來接收合成線程發(fā)過來的DrawQuad命令,然后根據(jù)DrawQuad命令,將其頁面內(nèi)容繪制到內(nèi)存中,最后再將內(nèi)存顯示在屏幕上。
          到這里,經(jīng)過這一系列的階段,編寫好的HTML、CSS、JavaScript等文件,經(jīng)過瀏覽器就會顯示出漂亮的頁面了。

          瀏覽 75
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  无码真人操逼 | 内射免费看 | 做爱无码| 婷婷综合成人网 | 国产婬乱片A片AAA毛姪片 |