當你開始輸入網址好比www.cnblogs.com時遊覽器就能夠在書籤或者歷史記錄裏面去搜索相關的網址推薦給你。javascript
導航的第一步是經過訪問的域名找出其IP地址。DNS查找過程以下:css
瀏覽器緩存 – 瀏覽器會緩存DNS記錄一段時間。 有趣的是,操做系統沒有告訴瀏覽器儲存DNS記錄的時間,這樣不一樣瀏覽器會儲存個自固定的一個時間(2分鐘到30分鐘不等)。html
系統緩存 – 若是在瀏覽器緩存裏沒有找到須要的記錄,瀏覽器會作一個系統調用(windows裏是gethostbyname)。這樣即可得到系統緩存中的記錄。java
路由器緩存 – 接着,前面的查詢請求發向路由器,它通常會有本身的DNS緩存。node
ISP DNS 緩存 – 接下來要check的就是ISP緩存DNS的服務器。在這通常都能找到相應的緩存記錄。web
遞歸搜索 – 你的ISP的DNS服務器從跟域名服務器開始進行遞歸搜索,從.com頂級域名服務器到Facebook的域名服務器。通常DNS服務器的緩存中會有.com域名服務器中的域名,因此到頂級服務器的匹配過程不是那麼必要了。面試
① 請求發起後,遊覽器首先會解析這個域名,首先它會查看本地硬盤的 hosts 文件,看看其中有沒有和這個域名對應的規則,若是有的話就直接使用 hosts 文件裏面的 ip 地址。數據庫
② 若是在本地的 hosts 文件沒有可以找到對應的 ip 地址,瀏覽器會發出一個 DNS請求到本地DNS(域名分佈系統)服務器 。本地DNS服務器通常都是你的網絡接入服務器商提供,好比中國電信,中國移動。windows
③查詢你輸入的網址的DNS請求到達本地DNS服務器以後,本地DNS服務器會首先查詢它的緩存記錄,若是緩存中有此條記錄,就能夠直接返回結果,此過程是遞歸的方式進行查詢。若是沒有,本地DNS服務器還要向DNS根服務器進行查詢瀏覽器
④根DNS服務器沒有記錄具體的域名和IP地址的對應關係,而是告訴本地DNS服務器,你能夠到域服務器上去繼續查詢,並給出域服務器的地址。這種過程是迭代的過程
⑤本地DNS服務器繼續向域服務器發出請求,在這個例子中,請求的對象是.com域服務器。.com域服務器收到請求以後,也不會直接返回域名和IP地址的對應關係,而是告訴本地DNS服務器,你的域名的解析服務器的地址
⑥最後,本地DNS服務器向域名的解析服務器發出請求,這時就能收到一個域名和IP地址對應關係,本地DNS服務器不只要把IP地址返回給用戶電腦,還要把這個對應關係保存在緩存中,以備下次別的用戶查詢時,能夠直接返回結果,加快網絡訪問。
相關問題:
什麼是DNS劫持?
DNS劫持(Domain Name System,域名劫持),是指在劫持的網絡範圍內攔截域名解析的請求,分析請求的域名,把審查範圍之外的請求放行,返回假的IP地址或者什麼都不作使請求失去響應,其效果就是對特定的網絡不能訪問或訪問的是假網址。簡單來講,就是你輸入的是知乎的網址,可是卻跳轉到了百度的頁面。
TCP/IP 分爲四層,在發送數據時,每層都要對數據進行封裝:
在前面的步驟咱們已經獲得服務器的 IP 地址,瀏覽器會開始構造一個 HTTP 報文,其中包括:
其中須要注意的點:
傳輸層會發起一條到達服務器的 TCP 鏈接,爲了方便傳輸,會對數據進行分割(以報文段爲單位),並標記編號,方便服務器接受時可以準確地還原報文信息。
在創建鏈接前,會先進行 TCP 三次握手。
關於 TCP/IP 三次握手,網上已經有不少段子和圖片生動地描述了。
相關知識點:
將數據段打包,並加入源及目標的IP地址,而且負責尋找傳輸路線。
判斷目標地址是否與當前地址處於同一網絡中,是的話直接根據 Mac 地址發送,不然使用路由表查找下一跳地址,以及使用 ARP 協議查詢它的 Mac 地址。
注意:在 OSI 參考模型中 ARP 協議位於鏈路層,但在 TCP/IP 中,它位於網絡層。
以太網協議
根據以太網協議將數據分爲以「幀」爲單位的數據包,每一幀分爲兩個部分:
Mac 地址
以太網規定了連入網絡的全部設備都必須具有「網卡」接口,數據包都是從一塊網卡傳遞到另外一塊網卡,網卡的地址就是 Mac 地址。每個 Mac 地址都是獨一無二的,具有了一對一的能力。
廣播
發送數據的方法很原始,直接把數據經過 ARP 協議,向本網絡的全部機器發送,接收方根據標頭信息與自身 Mac 地址比較,一致就接受,不然丟棄。
注意:接收方迴應是單播。
相關知識點:
接受過程就是把以上步驟逆轉過來,參見上圖。
大體流程
HTTPD
最多見的 HTTPD 有 Linux 上經常使用的 Apache 和 Nginx,以及 Windows 上的 IIS。
它會監聽獲得的請求,而後開啓一個子進程去處理這個請求。
處理請求
接受 TCP 報文後,會對鏈接進行處理,對HTTP協議進行解析(請求方法、域名、路徑等),而且進行一些驗證:
重定向
假如服務器配置了 HTTP 重定向,就會返回一個 301
永久重定向響應,瀏覽器就會根據響應,從新發送 HTTP 請求(從新執行上面的過程)。
URL 重寫
而後會查看 URL 重寫規則,若是請求的文件是真實存在的,好比圖片、html、css、js文件等,則會直接把這個文件返回。
不然服務器會按照規則把請求重寫到 一個 REST 風格的 URL 上。
而後根據動態語言的腳本,來決定調用什麼類型的動態文件解釋器來處理這個請求。
以 PHP 語言的 MVC 框架舉例,它首先會初始化一些環境的參數,根據 URL 由上到下地去匹配路由,而後讓路由所定義的方法去處理請求。
瀏覽器接收到來自服務器的響應資源後,會對資源進行分析。
首先查看 Response header,根據不一樣狀態碼作不一樣的事(好比上面提到的重定向)。
若是響應資源進行了壓縮(好比 gzip),還須要進行解壓。
而後,對響應資源作緩存。
接下來,根據響應資源裏的 MIME 類型去解析響應內容(好比 HTML、Image各有不一樣的解析方式)。
三、創建TCP連接
在拿到域名對應的IP地址後,會以隨機端口(1024~~65535)向WEB服務器程序80端口發起TCP的鏈接請求,這個鏈接請求進入到內核的TCP/IP協議棧(用於識別該鏈接請求,解封包,一層一層的剝開),還有可能要通過Netfilter防火牆(屬於內核的模塊)的過濾,最終到達WEB程序,最終創建了TCP/IP的鏈接,對於客戶端與服務器的TCP連接,必然要說的就是『三次握手』。
客戶端發送一個帶有SYN標誌的數據包給服務端,服務端收到後,回傳一個帶有SYN/ACK標誌的數據包以示傳達確認信息,最後客戶端再回傳一個帶ACK標誌的數據包,表明握手結束,鏈接成功。
通俗化以後就是:
客戶端:老弟我要跟你連接
服務端:好的,贊成了
客戶端:好嘞
創建TCP鏈接以後,發起HTTP請求,請求通常分爲三部分
請求方法URI協議/版本
請求頭(Request Header)
請求正文
下面是一個完整的請求
五、服務器端處理
服務器端收到請求後的由web服務器(準確說應該是http服務器)處理請求,諸如Apache、Ngnix、IIS等。web服務器解析用戶請求,知道了須要調度哪些資源文件,再經過相應的這些資源文件處理用戶請求和參數,並調用數據庫信息,最後將結果經過web服務器返回給瀏覽器客戶端。
爲了不服務器與客戶端雙方的資源佔用和損耗,當雙方沒有請求或響應傳遞時,任意一方均可以發起關閉請求。與建立TCP鏈接的3次握手相似,關閉TCP鏈接,須要4次握手。
能夠通俗化:
客戶端:老弟,我這邊沒數據要傳了,我們關閉連接吧
服務端:好的,接收到了,我看看我這邊還有沒有要傳的
服務端:我這邊也沒有了,關閉吧
客戶端:好嘞
三次握手&四次揮手以後
當網絡進程接收到的響應報文狀態碼,進行相應的操做。例如狀態碼爲 200 OK
時,會解析響應報文中的 Content-Type
首部字段,例如咱們這個過程 Content-Type
會出現 application/javascript
、text/css
、text/html
,即對應 Javascript
文件、CSS
文件、HTML
文件。
對於獲取到的HTML、CSS、JS、圖片等等資源。
瀏覽器經過解析HTML,生成DOM樹,解析CSS,生成CSS規則樹,而後經過DOM樹和CSS規則樹生成渲染樹。渲染樹與DOM樹不一樣,渲染樹中並無head、display爲none等沒必要顯示的節點。
在解析CSS的同時,能夠繼續加載解析HTML,但在解析執行JS腳本時,會中止解析後續HTML,這就會出現阻塞問題,關於JS阻塞相關問題,這裏不過多闡述,後面會單獨開篇講解。
你們都知道頁面渲染的過程也是面試中單獨會考的點,而且時常會由這個點延申出另外一個問題,即如何避免迴流和重繪。
渲染過程,是整個從理器輸入 URL 到頁面渲染過程的最後一步。而頁面渲染的過程能夠分爲 9 個步驟:
HTML
生成 DOM
樹CSS
生成 CSSOM
JavaScript
Render Tree
)2.5.1 構建 DOM 樹
因爲網絡進程傳輸給渲染進程的是 HTML
字符串,因此,渲染進程須要將 HTML
字符串轉化成 DOM
樹。
須要注意的是這個 DOM
樹不一樣於 Chrome-devtool
中 Element
選項卡的 DOM
樹,它是存在內存中的,用於提供 JavaScript
對 DOM
的操做。
構建 CSSOM
構建 CSSOM
的過程,即經過解析 CSS
文件、style
標籤、行內 style
等,生成 CSSOM
。而這個過程會作這幾件事:
規範 CSS
,即將 color: blue
轉化成 color: rgb()
形式,能夠理解成相似 ES6
轉 ES5
的過程
計算元素樣式,例如 CSS
樣式會繼承父級的樣式,如 font-size
、color
之類的。
CSS Object Model
是一組容許用 JavaScript
操縱 CSS
的 API
。詳細 API
講解能夠看 MDN
加載 JavaScript
一般狀況下,在構建 DOM
樹或 CSSOM
的同時,若是也要加載 JavaScript
,則會形成前者的構建的暫停。固然,咱們能夠經過 defer
或 sync
來實現異步加載 JavaScript
。雖然 defer
和 sync
均可以實現異步加載 JavaScript
,可是前者是在加載後,等待 CSSOM
和 DOM
樹構建完後才執行 JavaScript
,然後者是在異步加載完立刻執行,即便用 sync
的方式仍然會形成阻塞。
而 JavaScript
執行的過程,即編譯和運行 JavaScript
的過程。因爲 JavaScript
是解釋型的語言。因此這個過程會是這樣的:
Token
化Token
,生成 AST
(Abstract Sytanx Tree
) 抽象語法樹和建立上下文AST
,生成字節碼。在有了 DOM
樹和 CSSOM
以後,須要將二者結合生成渲染樹 Render Tree
,而且這個過程會去除掉那些 display: node
的節點。此時,渲染樹就具有元素和元素的樣式信息。
根據 Render Tree
渲染樹,對樹中每一個節點進行計算,肯定每一個節點在頁面中的寬度、高度和位置。
須要注意的是,第一次肯定節點的大小和位置的過程稱爲佈局,而第二次才被稱爲迴流
因爲層疊上下文的存在,渲染引擎會爲具有層疊上下文的元素建立對應的圖層,而諸多圖層的疊加就造成了咱們看到的一些頁面效果。例如,一些 3D
的效果、動畫就是基於圖層而造成的。
值得一提的是,對於內容溢出存在滾輪的狀況也會進行分層
對於存在圖層的頁面部分,須要進行有序的繪製,而對於這個過程,渲染引擎會將一個個圖層的繪製拆分紅繪製指令,並按照圖層繪製順序造成一個繪製列表。
光柵化
有了繪製列表後,渲染引擎中的合成線程會根據當前視口的大小將圖層進行分塊處理,而後合成線程會對視口附近的圖塊生成位圖,即光柵化。而渲染進程也維護了一個柵格化的線程池,專門用於將圖塊轉爲位圖。
柵格化的過程一般會使用 GPU
加速,例如使用 wil-change
、opacity
,就會經過 GPU
加速
顯示
當全部的圖塊都通過柵格化處理後,渲染引擎中的合成線程會生成繪製圖塊的指令,提交給瀏覽器進程。而後瀏覽器進程將頁面繪製到內存中。最後將內存繪製結果顯示在用戶界面上。
而這個整個從生成繪製列表、光柵化、顯示的過程,就是咱們常說的重繪的過程
結語
整個瀏覽器輸入 URL 到頁面渲染的過程涉及到的知識點很是廣,如 Chrome
多進程的架構、HTTP
通訊過程、瀏覽器解析 JavaScript
過程、瀏覽器繪製頁面過程以及一些計算機的基礎知識等等,而且,這整個過程的分析其實和 Chrome-devtools
密切相關。