一、前言
文章為了加深自我理解,參考:
前端經(jīng)典面試題: 從輸入URL到頁面加載發(fā)生了什么?
老生常談-從輸入url到頁面展示到底發(fā)生了什么
HTTP 請求頭與請求體
四種常見的POST提交方式
二、開始
從用戶開始輸入 url 到用戶見到頁面內(nèi)容,過程如下:
- 輸入 url
- 查找 ip ,從本地系統(tǒng)查找 hosts 文件,是否有 ip ? 有則下一步 : 沒有,進(jìn)行 DNS 解析
- TCP 連接
- 發(fā)送 HTTP 請求
- 服務(wù)器處理并返回 HTTP 請求
- 瀏覽器解析渲染頁面
- 用戶看到完整頁面
三、具體過程
I. 輸入 url
用戶在瀏覽器中輸入網(wǎng)址的時候,瀏覽器就只能的會從歷史記錄、書簽來搜索你當(dāng)前輸入的地址,如果你訪問的是有緩存過的地址,網(wǎng)頁可能直接展示出來。
II. 查找 ip
每個域名都是對應(yīng)有一個 ip 地址, 諸如 www.baidu.com 這些名稱只是用來方便用戶記憶。所以在獲取網(wǎng)頁內(nèi)容之前,瀏覽器得先知道這個網(wǎng)址的 ip 地址,才能去到對應(yīng)的服務(wù)器去獲取資源。
首先,瀏覽器會嘗試在本地的 hosts 文件中去查看是否有相應(yīng)的 ip 記錄,有的話就直接用對應(yīng)的 ip ,省去 DNS 解析。
DNS 解析
DNS (Domain Name System ,域名系統(tǒng))解析,就是一個網(wǎng)址到 ip 地址轉(zhuǎn)換的過程,解析是一個遞歸查詢的過程。
經(jīng)過多次的服務(wù)器往返后,得到了對應(yīng)的 ip 地址。從上述過程中,可以看出網(wǎng)址的解析是一個從右向左的過程,瀏覽器首先會去訪問
本地DNS服務(wù)器,查看是否有緩存 ip ,沒有,那么去訪問根服務(wù)器,每個網(wǎng)址的真正地址是www.baidu.com.,就是在網(wǎng)址后還有一個點,這個點就是指向根服務(wù)器,然后根服務(wù)器告訴你,你應(yīng)該去問COM頂級域名服務(wù)器,然后COM頂級域名服務(wù)器又告訴你,你應(yīng)該去問baidu.com服務(wù)器,這下終于找到負(fù)責(zé)人了,baidu.com服務(wù)器就會把它管理的www.baidu.com的 ip 地址返回告訴瀏覽器,費了這么大勁,瀏覽器終于如愿以償拿到 ip 了,接下來就可以向該 ip 拿頁面了。
問題是,如果每一次瀏覽器訪問個網(wǎng)站都要這么費勁,那用戶體驗不就很差?所以聰明的瀏覽器在訪問過一次之后,會去緩存下這個網(wǎng)址對應(yīng)的 ip 地址,下次就能直接用了。另外,聰明的本地DNS服務(wù)器、所有的服務(wù)器也會存下映射關(guān)系,以便下次使用。另外,也可以人為修改 Hosts 文件來指定網(wǎng)址的 ip 映射關(guān)系。
III. 建立 TCP 連接
瀏覽器在拿到 ip 地址之后,就開始準(zhǔn)備 HTTP 請求了,但首先要先和服務(wù)器建立連接通道,這時候就用到 TCP 建立三次握手了。 TCP 協(xié)議是用來建立對話通道的,在客戶端和服務(wù)器還沒對接之前,是無法確定各種各樣的請求的,舉個網(wǎng)絡(luò)上看到的例子:
- 甲: “喂!是乙嗎?”
- 乙: “是呀,我是乙?!?/li>
- 甲: “那我們開始對話吧!”
只有確保的請求服務(wù)器正確,才可以真正開始請求。另外,在請求頭會有一個
Connection: keep-alive,表示保持 TCP 連接,這樣客戶端在下次請求的時候,就不需要重新建立 TCP 連接了,雖然這樣會損耗部分服務(wù)器性能,但對雙方(客戶端、服務(wù)器)也都是有好處的。
IV. 發(fā)起 HTTP 請求
典型的 HTTP 請求消息頭域,如下:
POST/GET http://download.microtool.de:80/somedata.exe
Host: download.microtool.de
Accept:*/*
Pragma: no-cache
Cache-Control: no-cache
Referer: http://download.microtool.de/
User-Agent:Mozilla/4.04[en](Win95;I;Nav)
Range:bytes=554554-
總的來說 HTTP 請求包含三部分:請求行、請求頭、請求體(請求正文)。
a. 請求行
請求行分為三部分:請求方法、請求地址和協(xié)及版本。
HTTP/1.1定義的請求方法有 8 種:GET、POST、PUT、DELETE、PATCH、HEAD、OPTIONS、TRACE,最常用的兩種 GET 和 POST。以下為 GET 和 POST 區(qū)別的文章:
GET VS POST
注意: 在 POST、PUT、PATCH 三個請求中會包含請求體,其他的并沒有。
b. 請求頭
請求頭的詳細(xì)類型和內(nèi)容的詳細(xì)內(nèi)容谷歌搜索,一下是一次請求的樣例:
c. 請求體
請求體主要是用來存放數(shù)據(jù),數(shù)據(jù)類型存儲在 Content-Type 響應(yīng)頭上,接觸過的有:
-
application/x-www-form-urlencoded
最常見的 POST 提交數(shù)據(jù)方式,瀏覽器原生<form>表單,格式如下
POST http://www.example.com HTTP/1.1
Content-Type: application/x-www-form-urlencoded;charset=utf-8
title=test&sub%5B%5D=1&sub%5B%5D=2&sub%5B%5D=3
-
application/json
主要用來提交 JSON 格式的數(shù)據(jù),格式為:
POST http://www.example.com HTTP/1.1
Content-Type: application/json;charset=utf-8
{"title":"test","sub":[1,2,3]}
-
multipart/form-data
使用表單上傳文件時的格式,用于上傳文件,格式如:
POST http://www.example.com HTTP/1.1
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryrGKCBY7qhFd3TrwA
------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name="text"
title
------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name="file"; filename="chrome.png"
Content-Type: image/png
PNG ... content of chrome.png ...
------WebKitFormBoundaryrGKCBY7qhFd3TrwA--
-
text/xml
傳輸數(shù)據(jù),沒用過,不清楚,格式如下:
POST http://www.example.com HTTP/1.1
Content-Type: text/xml
<?xml version="1.0"?>
<methodCall>
<methodName>examples.getStateName</methodName>
<params>
<param>
<value><i4>41</i4></value>
</param>
</params>
</methodCall>
V. 服務(wù)器處理請求并返回 HTTP 報文
HTTP 請求也是三部分請求:狀態(tài)碼、相應(yīng)頭、響應(yīng)體(響應(yīng)報文)。
a. 狀態(tài)碼
狀態(tài)碼由3位數(shù)組成,第一個數(shù)字定義了相應(yīng)類別,共有五種可能取值:
- 1XX 消息:代表請求已被接受,需要繼續(xù)處理。這類響應(yīng)是臨時響應(yīng),通常情況下,服務(wù)器是不會給客戶端發(fā)送1xx響應(yīng)。
- 2XX 成功:代表請求成功被服務(wù)器接收、理解、接受。
- 3XX 重定向:代表客戶端需要采取進(jìn)一步的操作才能完成請求。
- 4XX 客戶端錯誤:代表客戶端看起來發(fā)生了錯誤,妨礙了服務(wù)器的處理。
- 5XX 服務(wù)器錯誤:表示服務(wù)器無法完成明顯有效的請求。
參考: HTTP 狀態(tài)碼
b. 響應(yīng)頭
涉及到服務(wù)器名稱、緩存、響應(yīng)體類型等,詳細(xì)內(nèi)容自行谷歌。
c. 響應(yīng)體
響應(yīng)體除了有 JSON 數(shù)據(jù)等一些其他數(shù)據(jù)類型外,也是獲取 HTML、CSS、JS、圖片等文件的地方。
HTTP 和 HTTPS
HTTPS 是 HTTP 請求前,客戶端與服務(wù)器先進(jìn)行一次握手(TLS/SSL握手),用于數(shù)據(jù)加密,具體加密我不懂,參考這里:圖解SSL/TLS協(xié)議。很明顯的是,雖然 HTTPS 更為安全,但與 HTTP 相比,多了一次連接,肯定會影響一部分的加載速度。一張圖說明:
VI. 瀏覽器解析渲染頁面
瀏覽器解析服務(wù)器返回的 HTML 時,是從上往下順序解析的,遇到 CSS link、JS link 就會向服務(wù)器請求該資源,瀏覽器也開始生成 DOM 結(jié)構(gòu),但需要注意的是,CSS 文件不會阻塞 DOM 結(jié)構(gòu)的生成,而 JS 文件會(因為 JS 可以操作 DOM),所以如果在 HTML 頭部開始解析 JS 的話,瀏覽器會等 JS 請求完并且初始化結(jié)束才會繼續(xù)生成 DOM 結(jié)構(gòu)。這也是為什么 JS 經(jīng)常放在
<body>最后,而且用的是window.onload=function(){}。不過可以在<script async></script>加個async,告訴瀏覽器不用等我 JS 啦,趕緊開始生成你的 DOM 樹結(jié)構(gòu)(async是異步加載的意思)。
DOM 樹生成后,就要上色,這時候就是 CSS 的作用了。一張圖說明:

另外,這里有個視頻很好的講解了瀏覽器對網(wǎng)頁的處理:網(wǎng)站性能優(yōu)化(中/英)
VII. 用戶看到完整頁面
到此,用戶終于能完整的看到一個頁面了,沒想到吧,在這么短短2秒,瀏覽器做了這么多事,還跑了這么遠(yuǎn),不容易。要學(xué)的內(nèi)容還很多,這是一篇前端新手的理解,參考很多東西,如有出錯,請嚴(yán)厲指出~