摘要:響應(yīng)由三個部分組成,分別是狀態(tài)行消息報頭響應(yīng)正文。詳情參考小汪之前寫的文章瀏覽器內(nèi)核之解釋器和模型解釋解釋過程是指從字符串經(jīng)過解釋器處理后變成渲染引擎內(nèi)部規(guī)則的表示過程。
前言
小汪最近在看【W(wǎng)ebKit 技術(shù)內(nèi)幕】一書,說實話,這本書寫的太官方了,不通俗易懂。
但是看完書,對瀏覽器內(nèi)核的 WebKit 有了進一步的了解,所以從瀏覽器內(nèi)核出發(fā),寫這篇文章以記錄學(xué)到的知識,以加深對 WebKit 的理解。
相信很多開發(fā)人員在面試時都遇到這個問題,這道題可說是非常非常難的,因為深度可以非常深,廣度可以非常廣。這題是非常能考查一個前端開發(fā)人員的知識體系的題目。
1. 大致過程當(dāng)你這樣子回答的時候:
用戶輸入 url 地址,瀏覽器查詢 DNS 查找對應(yīng)的請求 IP 地址
建立 TCP 連接
瀏覽器向服務(wù)器發(fā)送 http 請求,如果服務(wù)器段返回以 301 之類的重定向,瀏覽器根據(jù)相應(yīng)頭中的 location 再次發(fā)送請求
服務(wù)器端接受請求,處理請求生成 html 代碼,返回給瀏覽器,這時的 html 頁面代碼可能是經(jīng)過壓縮的
瀏覽器接收服務(wù)器響應(yīng)結(jié)果,如果有壓縮則首先進行解壓處理,緊接著就是頁面解析渲染
解析該過程分為:解析 HTML,構(gòu)建 DOM 樹,DOM 樹與 CSS 樣式進行附著構(gòu)造呈現(xiàn)樹,布局、繪制
雖然這大致的過程是對的,但回答不上細節(jié) !深度不夠?。?!
面試官給你的臉色是:“很遺憾,這不是我們要的回答 ! ”
2. 詳細過程下面讓我們扒下各個過程細節(jié)的外衣,坦誠相見吧 !
2.1 輸入地址瀏覽器引入了 DNS 預(yù)取技術(shù)。它是利用現(xiàn)有的 DNS 機制,提前解析網(wǎng)頁中可能的網(wǎng)絡(luò)連接。
當(dāng)我們開始在瀏覽器中輸入網(wǎng)址的時候,瀏覽器其實就已經(jīng)在智能的匹配可能得 url 了。它會從歷史記錄,書簽等地方,找到已經(jīng)輸入的字符串可能對應(yīng)的 url ,找到同輸入的地址很匹配的項,然后給出智能提示,讓你可以補全 url 地址。用戶還沒有按下 enter 鍵, 瀏覽器已經(jīng)開始使用 DNS 預(yù)取技術(shù)解析該域名了。
對于 chrome 的瀏覽器,如果有該域名相關(guān)的緩存,它會直接從緩存中把網(wǎng)頁展示出來,就是說,你還沒有按下 enter,頁面就出來了。如果沒有緩存,就還是會重新請求資源。
2.2 查詢 DNS 查找對應(yīng)的請求 IP 地址假設(shè)輸入 www.baidu.com,大概過程:
瀏覽器搜索自己的 DNS 緩存。
在瀏覽器緩存中沒找到,就在操作系統(tǒng)緩存中查找,這一步中也會查找本機的 hosts 看看有沒有對應(yīng)的域名映射。
在系統(tǒng)中也沒有的話,就到你的路由器來查找,因為路由器一般也會有自己的 DNS 緩存。
若沒有,則操作系統(tǒng)將域名發(fā)送至 本地域名服務(wù)器——遞歸查詢方式,本地域名服務(wù)器 查詢自己的 DNS 緩存,查找成功則返回結(jié)果,否則,采用迭代查詢方式。本地域名服務(wù)器一般都是你的網(wǎng)絡(luò)接入服務(wù)器商提供,比如中國電信,中國移動。
本地域名服務(wù)器 將得到的 IP 地址返回給操作系統(tǒng),同時自己也將 IP 地址緩存起來。
操作系統(tǒng)將 IP 地址返回給瀏覽器,同時自己也將 IP 地址緩存起來,以備下次別的用戶查詢時,可以直接返回結(jié)果,加快網(wǎng)絡(luò)訪問。
至此,瀏覽器已經(jīng)得到了域名對應(yīng)的 IP 地址。
參考文章:
https://blog.csdn.net/wlk2064819994/article/details/79756669
https://blog.csdn.net/dojiangv/article/details/51794535
TCP 是一種面向有連接的傳輸層協(xié)議。
它可以保證兩端(發(fā)送端和接收端)通信主機之間的通信可達。
它能夠處理在傳輸過程中丟包、傳輸順序亂掉等異常情況;此外它還能有效利用寬帶,緩解網(wǎng)絡(luò)擁堵。
三次握手的步驟:(抽象派)
客戶端:hello,你是server么? 服務(wù)端:hello,我是server,你是client么 客戶端:yes,我是client
在 TCP 連接建立完成之后就可以發(fā)送 HTTP 請求了。
然后,待到斷開連接時,需要進行四次揮手(因為是全雙工的,所以需要四次揮手)
四次揮手的步驟:(抽象派)
主動方:我已經(jīng)關(guān)閉了向你那邊的主動通道了,只能被動接收了 被動方:收到通道關(guān)閉的信息 被動方:那我也告訴你,我這邊向你的主動通道也關(guān)閉了 主動方:最后收到數(shù)據(jù),之后雙方無法通信2.4 服務(wù)器收到請求并響應(yīng) HTTP 請求
在接收和解釋請求消息后,服務(wù)器返回一個HTTP響應(yīng)消息。
HTTP 響應(yīng)由三個部分組成,分別是:狀態(tài)行、消息報頭、響應(yīng)正文。
狀態(tài)代碼:由三位數(shù)字組成,第一個數(shù)字定義了響應(yīng)的類別,且有五種可能取值:
1xx:指示信息--表示請求已接收,繼續(xù)處理
2xx:成功--表示請求已被成功接收、理解、接受
3xx:重定向--要完成請求必須進行更進一步的操作
4xx:客戶端錯誤--請求有語法錯誤或請求無法實現(xiàn)
5xx:服務(wù)器端錯誤--服務(wù)器未能實現(xiàn)合法的請求
常見狀態(tài)代碼、狀態(tài)描述、說明:
200 OK :客戶端請求成功
400 Bad Request :客戶端請求有語法錯誤,不能被服務(wù)器所理解
401 Unauthorized :請求未經(jīng)授權(quán),這個狀態(tài)代碼必須和WWW-Authenticate報頭域一起使用
403 Forbidden :服務(wù)器收到請求,但是拒絕提供服務(wù)
404 Not Found :請求資源不存在,eg:輸入了錯誤的URL
500 Internal Server Error :服務(wù)器發(fā)生不可預(yù)期的錯誤
503 Server Unavailable :服務(wù)器當(dāng)前不能處理客戶端的請求,一段時間后可能恢復(fù)正常
HTTP消息報頭包括:普通報頭、請求報頭、響應(yīng)報頭、實體報頭。具體不作介紹。
響應(yīng)正文:就是服務(wù)器返回的資源的內(nèi)容
2.5 瀏覽器接收服務(wù)器響應(yīng)結(jié)果并處理在瀏覽器沒有完整接受全部HTML文檔時,它就已經(jīng)開始顯示這個頁面了,不同瀏覽器可能解析的過程不太一樣,這里我們只介紹 WebKit 的渲染過程。
渲染步驟大致可以分為以下幾步:
1. 解析HTML,構(gòu)建 DOM 樹 2. 解析 CSS ,生成 CSS 規(guī)則樹 3. 合并 DOM 樹和 CSS 規(guī)則,生成 render 樹 4. 布局 render 樹( Layout / reflow ),負責(zé)各元素尺寸、位置的計算 5. 繪制 render 樹( paint ),繪制頁面像素信息 6. 瀏覽器會將各層的信息發(fā)送給 GPU,GPU 會將各層合成( composite ),顯示在屏幕上
其中每個解釋的過程中,WebKit 都提供了很多相關(guān)的類來一步一步地解釋對應(yīng)的內(nèi)部模塊,這里面不做詳細描述。
下面根據(jù)上面的大致過程來一步步細解。
瀏覽器在解析html文件時, 是WebKit 中的 HTML 解釋器的將網(wǎng)絡(luò)或者本地磁盤獲取的 HTML 網(wǎng)頁和資源從字節(jié)流解釋成 DOM 樹結(jié)構(gòu)。具體過程如下 :
在 WebKit 中這一過程如下:首先是字節(jié)流,經(jīng)過解碼之后是字符流,然后通過詞法分析器會被解釋成詞語(Tokens),之后經(jīng)過語法分析器構(gòu)建成節(jié)點,最后這些節(jié)點被組建成一棵 DOM 樹。
瀏覽器在解析html文件過程中,會 ”自上而下“ 加載,并在加載過程中進行解析渲染。在解析過程中,如果遇到請求外部資源時,如圖片、外鏈的CSS、iconfont等,請求過程是異步的,并不會影響html文檔進行加載,且統(tǒng)一交由 Browser 進程來處理,這使得資源在不同網(wǎng)頁間的共享變得很容易。
HTML 的解釋、布局和渲染等工作基本上就是工作在渲染線程完成的(這不是絕對的)。因為 DOM 樹只能在渲染線程上創(chuàng)建和訪問,這也就是說構(gòu)建 DOM 樹的過程只能在渲染線程中進行,但是,從字符到詞語這個階段可以交給另外的多帶帶的線程來做。
而且因為有 DNS 預(yù)取技術(shù),當(dāng)用戶正在瀏覽當(dāng)前網(wǎng)頁的時候,Chromium 提取網(wǎng)頁中的超鏈接,將域名抽取出來,利用比較少的 CPU 和網(wǎng)絡(luò)帶寬來解析這些域名或者 IP 地址,這樣一來,用戶根本感覺不到這一過程。當(dāng)用戶單擊這些鏈接的時候,可以節(jié)省不少時間,特別在域名解析比較慢的時候,效果特別明顯。
解析過程中,瀏覽器首先會解析 HTML 文件構(gòu)建 DOM 樹,然后解析 CSS 文件構(gòu)建 Render樹,等到 Render 樹構(gòu)建完成后,瀏覽器開始布局 Render 樹并將其繪制到屏幕上。
詳情參考小汪之前寫的文章:瀏覽器內(nèi)核之 HTML 解釋器和 DOM 模型
CSS 解釋過程是指從 CSS 字符串 經(jīng)過 CSS 解釋器 處理后變成渲染引擎內(nèi)部規(guī)則的表示過程。
生成樣式規(guī)則之后,會進行樣式規(guī)則匹配,WebKit 會為其中的一些節(jié)點(只限于可視節(jié)點)選擇合適的樣式信息,規(guī)則的匹配則是由 ElementRuleCollector 類來計算并獲得,它根據(jù)元素的屬性等,并從 DocumentRuleSets 類中獲取規(guī)則集合,依次按照 ID、類別、標(biāo)簽等選擇器信息逐次匹配獲得元素的樣式。
最后,WebKit 對這些規(guī)則進行排序。對于該元素需要的樣式屬性,WebKit 選擇從高優(yōu)先級規(guī)則中選取,并將樣式屬性值返回。
從整個網(wǎng)頁的加載和渲染過程來看,CSS 解釋和規(guī)則匹配處于 DOM 樹建立之后,RenderObject 樹建立之前,CSS 解釋器解釋后的結(jié)果會保存起來,然后 RenderObject 樹基于該結(jié)果來進行規(guī)范匹配和布局計算。當(dāng)網(wǎng)頁有用戶交互或者動畫等動作的時候,通過 CSSDOM 等技術(shù),JavaScript 代碼同樣可以非常方便地修改 CSS 代碼,WebKit 此時需要重新解釋樣式并重復(fù)以上這一過程。
參考小汪之前寫的文章:瀏覽器內(nèi)核之 CSS 解釋器和樣式布局
當(dāng)文檔加載過程中遇到 js 文件,html 文檔會掛起渲染(加載解析渲染同步)的線程,不僅要等待文檔中 js 文件加載完畢,還要等待解析執(zhí)行完畢,才可以恢復(fù) html 文檔的渲染線程。因為 JS 有可能會修改 DOM,最為經(jīng)典的 document.write,這意味著,在 JS 執(zhí)行完成前,后續(xù)所有資源的下載可能是沒有必要的,這是 js 阻塞后續(xù)資源下載的根本原因。所以我們平時的代碼中,js 是放在 html 文檔末尾的。
而且當(dāng)遇到執(zhí)行 JavaScript 代碼的時候,WebKit 先暫停當(dāng)前 JavaScript 代碼的執(zhí)行,使用預(yù)先掃描器 HTMLPreloadScanner 類來掃描后面的詞語。如果 WebKit 發(fā)現(xiàn)它們需要使用其他資源,那么使用預(yù)資源加載器 HTMLPreloadScanner 類來發(fā)送請求,在這之后,才執(zhí)行 JavaScript 代碼。預(yù)先掃描器本身并不創(chuàng)建節(jié)點對象,也不會構(gòu)建 DOM 樹,所以速度比較快。
當(dāng) DOM 樹構(gòu)建完之后,WebKit 觸發(fā) “DOMContentLoaded” 事件,注冊在該事件上的 JavaScript 函數(shù)會被調(diào)用。當(dāng)所在資源都被加載完之后,WebKit 觸發(fā) “onload” 事件。
WebKit 將 DOM 樹創(chuàng)建過程中需要執(zhí)行的 JavaScript 代碼交由 HTMLScriptRunner 類來負責(zé)。工作方式很簡單,就是利用 JavaScript 引擎來執(zhí)行 Node 節(jié)點中包含的代碼。
JS 的解析是由瀏覽器中的 JavaScript 引擎完成的。JS是單線程運行,也就是說,在同一個時間內(nèi)只能做一件事,所有的任務(wù)都需要排隊,前一個任務(wù)結(jié)束,后一個任務(wù)才能開始。但是又存在某些任務(wù)比較耗時,如 IO 讀寫等,所以需要一種機制可以先執(zhí)行排在后面的任務(wù),這就是:同步任務(wù)(synchronous)和異步任務(wù)(asynchronous)。
JS 的執(zhí)行機制就可以看做是一個主線程加上一個任務(wù)隊列(task queue)。同步任務(wù)就是放在主線程上執(zhí)行的任務(wù),異步任務(wù)是放在任務(wù)隊列中的任務(wù)。所有的同步任務(wù)在主線程上執(zhí)行,形成一個執(zhí)行棧; 異步任務(wù)有了運行結(jié)果就會在任務(wù)隊列中放置一個事件;腳本運行時先依次運行執(zhí)行棧,然后會從任務(wù)隊列里提取事件,運行任務(wù)隊列中的任務(wù),這個過程是不斷重復(fù)的,所以又叫做事件循環(huán)(Event loop)。
參考小汪之前寫的文章:瀏覽器之 javaScript 引擎
HTML 經(jīng)過 WebKit 解釋之后,生成 DOM 樹。在 DOM 樹構(gòu)建完成之后,WebKit 會為 DOM 樹節(jié)點構(gòu)建 RenderObject 樹,再通過 RenderObject 樹構(gòu)建出 RenderLayer 樹。
RenderObject 樹是基于 DOM 樹建立起來的一棵新樹,是為了布局計算和渲染等機制而構(gòu)建的一種新的內(nèi)部表示。RenderObject 樹節(jié)點和 DOM 節(jié)點不是一一對應(yīng)關(guān)系,因為有可視節(jié)點(常用的 div img 標(biāo)簽等)與不可視節(jié)點(如 head、meta 標(biāo)簽),不可視節(jié)點是不會構(gòu)成 RenderObject 樹的。
網(wǎng)頁是有層次結(jié)構(gòu)的,可以分層的,一是為了方便設(shè)置網(wǎng)頁的層次,二是為了 WebKit 處理上的便利,為了簡化渲染的邏輯。
而且 RenderLayer 節(jié)點和 RenderObject 節(jié)點不是一一對應(yīng)關(guān)系,而是一對多的關(guān)系。
當(dāng) WebKit 創(chuàng)建 RenderObject 對象之后,每個對象是不知道自己的位置、大小等信息的,WebKit 根據(jù)框模型來計算它們的位置,大小等信息的過程稱為布局計算。
布局計算是一個遞歸的過程,因為一個節(jié)點的大小通常需要先計算它的子女節(jié)點的位置,大小等信息。
當(dāng)用戶 網(wǎng)頁的動畫、翻滾網(wǎng)頁、JavaScript 代碼通過 CSSDOM 等操作時還會有重新布局。
參考小汪之前寫的文章:瀏覽器內(nèi)核之 CSS 解釋器和樣式布局
在 WebKit 中,繪圖操作就是繪圖上下文,所有繪圖的操作都是在該上下文中來進行的。
繪圖上下文可以分成兩種類型:
一是 2D 圖形上下文(GraphicsContext),用來繪制 2D 圖形的的上下文;
二是 3D 繪圖上下文,是用來繪制 3D 圖形的上下文。
2D 繪圖上下文具體的作用:提供基本繪圖單元的繪制接口以及設(shè)置繪圖的樣式。繪圖接口包括畫點,畫線、畫圖片、畫多邊形、畫文字等,繪圖樣式包括顏色、線寬、字號大小、漸變等。
關(guān)于 3D 繪圖上下文,它的主要用處是支持 CSS3D、WebGL 等。
網(wǎng)頁的渲染方式,有三種方式,一是軟件渲染,二是硬件加速渲染,三可以說是混合模式。
如果繪圖操作使用 CPU 來完成,稱之為軟件繪圖。
如果繪圖操作由 GPU 來完成,稱之為 GPU 硬件加速繪圖。
理想情況下,每個層都有個繪制的存儲區(qū)域,這個存儲區(qū)域用來保存繪圖的結(jié)果。最后,需要將這些層的內(nèi)容合并到同一個圖像之中,可以稱之為合成(Compositing),使用了合成技術(shù)的渲染稱之為合成化渲染。
所以,在完成構(gòu)建 DOM 樹之后,WebKit 會調(diào)用繪圖操作、軟件渲染或者硬件加速渲染或者兩者都有,將模型繪制出來,呈現(xiàn)在屏幕上。
至此,瀏覽器渲染完成。
詳情參考小汪之前寫的文章:瀏覽器內(nèi)核之渲染基礎(chǔ)
最后現(xiàn)在,當(dāng)面試官再問你 “從敲入 URL 到瀏覽器渲染完成” 的時候,你的內(nèi)心是不是這樣的 ?
你以為本文就這么結(jié)束了 ? 精彩在后面 !??!
對 全棧修煉 有興趣的朋友可以掃下方二維碼關(guān)注我的公眾號
我會不定期更新有價值的內(nèi)容,長期運營。
關(guān)注公眾號并回復(fù) 福利 可領(lǐng)取免費學(xué)習(xí)資料,福利詳情請猛戳: Python、Java、Linux、Go、node、vue、react、javaScript
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/97788.html
摘要:在上述過程再細化為瀏覽器搜索自己的緩存。至此,瀏覽器已經(jīng)得到了域名對應(yīng)的地址。具體過程如下在中這一過程如下首先是字節(jié)流,經(jīng)過解碼之后是字符流,然后通過詞法分析器會被解釋成詞語,之后經(jīng)過語法分析器構(gòu)建成節(jié)點,最后這些節(jié)點被組建成一棵樹。 面試的時候,我們經(jīng)常會被問從在瀏覽器地址欄中輸入 url 到頁面展現(xiàn)的短短幾秒內(nèi)瀏覽器究竟做了什么?那么瀏覽器到底做了啥? 瀏覽器的多進程架構(gòu)一個好的程...
摘要:在上述過程再細化為瀏覽器搜索自己的緩存。至此,瀏覽器已經(jīng)得到了域名對應(yīng)的地址。具體過程如下在中這一過程如下首先是字節(jié)流,經(jīng)過解碼之后是字符流,然后通過詞法分析器會被解釋成詞語,之后經(jīng)過語法分析器構(gòu)建成節(jié)點,最后這些節(jié)點被組建成一棵樹。 面試的時候,我們經(jīng)常會被問從在瀏覽器地址欄中輸入 url 到頁面展現(xiàn)的短短幾秒內(nèi)瀏覽器究竟做了什么?那么瀏覽器到底做了啥? 瀏覽器的多進程架構(gòu)一個好的程...
摘要:在上述過程再細化為瀏覽器搜索自己的緩存。至此,瀏覽器已經(jīng)得到了域名對應(yīng)的地址。具體過程如下在中這一過程如下首先是字節(jié)流,經(jīng)過解碼之后是字符流,然后通過詞法分析器會被解釋成詞語,之后經(jīng)過語法分析器構(gòu)建成節(jié)點,最后這些節(jié)點被組建成一棵樹。 面試的時候,我們經(jīng)常會被問從在瀏覽器地址欄中輸入 url 到頁面展現(xiàn)的短短幾秒內(nèi)瀏覽器究竟做了什么?那么瀏覽器到底做了啥? 瀏覽器的多進程架構(gòu)一個好的程...
摘要:線程的劃分尺度小于進程,使得多線程程序的并發(fā)性高。線程在執(zhí)行過程中與進程還是有區(qū)別的。每個獨立的線程有一個程序運行的入口順序執(zhí)行序列和程序的出口。從邏輯角度來看,多線程的意義在于一個應(yīng)用程序中,有多個執(zhí)行部分可以同時執(zhí)行。 showImg(https://segmentfault.com/img/bVbv2GE?w=900&h=400); 前言 本文講解 56 道 JavaScript...
閱讀 3530·2021-11-23 10:10
閱讀 3292·2019-08-30 14:03
閱讀 2066·2019-08-30 13:09
閱讀 3392·2019-08-29 15:29
閱讀 1540·2019-08-29 11:23
閱讀 2002·2019-08-28 18:28
閱讀 2840·2019-08-26 13:34
閱讀 2168·2019-08-26 11:32