注意看,這個使用者叫小美,他在位址列輸入了一串URL地址,然後竟然發生了不可思議的事情!
01、輸入URL發生了什麼?
從輸入URL開始,到頁面呈現出來,簡單來說分為四個步驟:
- ① 建立連線:建立與伺服器的網路通訊連線,為正式資料傳輸做準備。
- ?DNS域名解析:首先是取出URL中的域名,透過DNS域名解析獲得到對應IP地址,計算機的TCP連線是基於IP地址的,域名只是給使用者看的。
- ?建立TCP連線:HTTP連線是建立在TCP協議之上的,其資料傳輸功能是由TCP完成的。用上面獲得IP地址,建立TCP連線:①請求?? ➤ ②確認?? ➤ ③建立連線??,對,就是著名的三次握手??。關於HTTP協議及連線過程可看上一篇 HTTP協議圖文簡述。
- 如果是HTTPS連線,還需要多一步,進行SSL/TLS握手,建立加密通訊機制。
- ② 獲取資料:向服務端傳送HTTP請求獲取網頁資料。
- ?傳送HTTP請求:構造HTTP報文:請求頭部
header
+ 請求包體body
,然後傳送HTTP請求。 - ?服務端響應:伺服器監聽80、443埠,當收到客戶端的請求後響應處理,把HTML網頁資料放在HTTP報文的包體
body
中,返回給客戶端。
- ?傳送HTTP請求:構造HTTP報文:請求頭部
- ③ 解析渲染:客戶端解析服務端返回的HTML網頁內容,並進行渲染,最終呈現給使用者。
- ?在解析過程中如果還有其他資源(如圖片、JS、CSS),會繼續構造相應的HTTP請求,重複步②、③驟獲取資料、解析渲染。如果資源來自其他域名,則還需先經過步驟①建立連線。
- ④ 斷開連線:完成頁面的所有請求後,發起 TCP 四次揮手,斷開連線。
✍️畫個時序圖吧!
02、URL地址的構成?
URL(Uniform Resource Locator)統一資源定位符,用來標識網路上的唯一資源的地址,就是俗稱的 網址。
?URL格式:
scheme://domain[:port][/path/.../][file][?query][#anchor]
主要包含以下幾個部分:
- 協議(schema):網路服務的型別,http、https等。
- 域名(domain):或主機名,一般域名為
www.taobao.com
,也可以為IP地址(60.191.55.43
)。 - 埠號(port):主機的埠號,HTTP=80,HTTPS=443,預設埠號可省略。
- 網站的資源地址:屬於網站內部的內容地址,包括多個部分:
- 資源路徑:網站根目錄下的子目錄(path)+資源名稱(filename)。
- 引數(?query):問號"
?
"後面的key=value&...
結構的引數,用於伺服器查詢。 - 錨點(#anchor):網址最後
#
開頭的部分,網頁內部定位,在瀏覽器端使用,服務端不會管。
?URL常見協議:
- http:超文字傳輸協議訪問遠端網路資源,
https
為安全版本的http。 - file:訪問本地計算機資源。
- mailto:訪問電子郵箱地址。
- ftp:訪問遠端FTP伺服器上的檔案資源,預設埠21。
03、建立連線
3.1、DNS域名解析
DNS 域名解析系統(Domain Name System) 是用來解析域名的(domain name),把域名解析為計算機能夠識別的IP 地址(IP address)。
- 域名 面向使用者:為了便於人們使用,易於識別、記憶,相當於是對IP地址的裝飾,如
www.baidu.com
。 - IP地址 面向機器:是網路IP協議提供的邏輯地址,固定長度的數字符號,給機器用的,IPv4 是 32 位,IPv6 是 128 位。
ping www.baidu.com //14.215.177.38
DNS 系統中儲存了一張域名、IP 地址的對映表,記錄了網際網路上所有的域名和IP的資料。但實際的上這張表不是在單一伺服器上,他是分散式儲存在全球很多地方。所以域名解析的過程,就是在這些分散式的DNS伺服器上去檢索,直到找到域名對應的IP地址。
- ?本地快取,如
hosts
檔案、瀏覽器的域名快取、系統域名快取、路由器快取。快取是個好東西,最近解析過的域名會被快取起來,所以第二次再開啟網頁更快了,當然這裡還有其他原因,如HTTP連線快取、已下載的資源快取等。 - ?公共域名伺服器,一般是網路服務商
ISP
(internet server provider )提供的的DNS servers
,如如中國電信、中國移動。或本機設定的DNS,如阿里、百度、Google提供的DNS伺服器。 - ?根伺服器:這是整個網際網路的核心伺服器,屬於頂級域名伺服器,全球共13臺。這裡存了所有DNS伺服器的索引,在這裡查詢對應的主域名伺服器。
- ?域名伺服器,如
.com
為頂級域名伺服器,到該伺服器繼續查詢,如此遞迴/迭代查詢,直到找到對應IP返回給客戶端。
? DNS 是基於 UDP協議 通訊的。
- 在實際網頁中,可能有來自多個站點的資源,不僅有自己網站的網頁內容,還有A網站的圖片、B網站的JS庫,C網站的CSS庫等,就意味著每一個域名都要先經過DNS查詢獲取具體的IP地址。
3.2、常用公共DNS伺服器
DNS伺服器 | IP地址 |
---|---|
阿里 DNS: | 223.5.5.5 、 223.6.6.6 |
百度 DNS: | 180.76.76.76 |
Google DNS: | 8.8.8.8 、 8.8.4.4 |
360 DNS: | 101.226.4.6 、 123.125.81.6 |
騰訊雲DNS | 183.60.83.19 |
114DNS | 114.114.114.114 、114.114.115.115 |
3.3、維持連線
完成一次 HTTP 請求後,伺服器並不是馬上斷開與客戶端的連線。在 HTTP/1.1 的header
中Connection: keep-alive
是預設啟用的,表示持久連線,以便後續請求可以複用HTTP連線。實際一個網頁往往有多個請求(圖片、CSS、JS),後面的請求就不用重新建立網路連線了,從而節約開銷,提高載入速度。
但是一直保持TCP連線,是有開銷的,特別是大併發場景時的服務端,因此長連結也是有一定限制的,如果長時間都沒有請求就關閉了。另外如果一方意外斷開了,如瀏覽器被強制關閉了,服務端也不可能一直等著,這就需要一個保活探測機制,類似心跳來判斷對方是否還活著。
在反向代理軟體 Nginx 中,持久連線超時時間預設值為 75 秒,如果 75 秒內沒有新到達的請求,則斷開與客戶端的連線。同時,瀏覽器每隔 45 秒會向伺服器傳送 TCP keep-alive 探測包,來判斷 TCP 連線狀況,如果沒有收到 ACK 應答,則主動斷開與伺服器的連線。
04、請求、響應資料
瀏覽器構造HTTP報文:請求頭部header
+請求包體body
,然後傳送HTTP請求。示例中的“https://www.baidu.com/s?wd=china”
請求為GET,引數在URL上,請求頭body沒有資料。關於HTTP協議及請求、應答過程更多可看上一篇 HTTP協議圖文簡述。
?請求HTTP報文:
GET /s?wd=china HTTP/1.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
Connection: keep-alive
Host: www.baidu.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36 Edg/107.0.1418.35
sec-ch-ua: "Microsoft Edge";v="107", "Chromium";v="107", "Not=A?Brand";v="24"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
?響應HTTP報文:伺服器監聽80、443等WEB埠,當監聽收到客戶端的請求後響應處理,把網頁資料放在HTTP報文的包體body
中,返回給客戶端。服務端的實際處理過程要複雜的多,可能還涉及負載均衡、反向代理、閘道器、WEB伺服器、應用伺服器、資料庫,及CDN等。
- 如下示例,響應頭
header
中有些是百度自定義擴充套件的欄位。
HTTP/1.1 200 OK
Bdpagetype: 3
Bdqid: 0xadfe12d00008e897
Cache-Control: private
Connection: keep-alive
Content-Encoding: br
Content-Type: text/html;charset=utf-8
Date: Fri, 25 Nov 2022 09:37:39 GMT
Server: BWS/1.1
Set-Cookie: delPer=0; path=/; domain=.baidu.com
Set-Cookie: BD_CK_SAM=1;path=/
Set-Cookie: PSINO=6; domain=.baidu.com; path=/
Set-Cookie: BDSVRTM=26; path=/
Strict-Transport-Security: max-age=172800
Vary: Accept-Encoding
X-Frame-Options: sameorigin
X-Ua-Compatible: IE=Edge,chrome=1
Transfer-Encoding: chunked
- 響應內容:就是HTML字串內容,共計7084行,這些內容在下一步由瀏覽器渲染引擎進行解析,並最終渲染展示出來。
<!DOCTYPE html>
<!--STATUS OK-->
<html class="">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<meta content="always" name="referrer">
<meta name="theme-color" content="#ffffff">
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" />
<link rel="icon" sizes="any" mask href="//www.baidu.com/img/baidu_85beaf5496f291521eb75ba38eacbd87.svg">
<link rel="search" type="application/opensearchdescription+xml" href="/content-search.xml" title="百度搜尋" />
<title>china_百度搜尋</title>
</head>
<body>
</body>
</html>
05、瀏覽器解析、渲染
解析服務端返回的HTML網頁資料,並進行渲染,這個過程的5個關鍵步驟:①構建DOM ➤ ②構建CSS規則樹 ➤ ③構建渲染樹 ➤ ④佈局 ➤ ⑤繪製。
✍️畫個圖大概就是這樣:
- ① DOM 樹:根據 HTML 解析出 DOM 樹(DOM Tree)
- ?從上往下解析HTML內容,按照標籤結構構造DOM樹,構建過程採用深度優先遍歷,即先構建當前節點的所有子節點,然後才繼續下一個兄弟節點。
- ?當遇到外部
css
連結檔案、圖片資源時,會非同步發起資源請求,不影響HTML解析。 - ?解析中如遇到
<script>
指令碼(沒有async
、defer
),會等待指令碼執行完才繼續,如果是外部JS檔案,還得等JS先下載再執行。這麼做的目的是JS程式碼可能會修改DOM樹和CSS樣式,避免造成迴流和重繪。 - 遇到設定
async
和defer
的<script>
指令碼,建立新的執行緒非同步載入,繼續解析HTML。async
載入完馬上執行,defer
在DOMContentLoaded前執行。
- ② CSS規則樹:根據 CSS 解析生成 CSS 規則樹(CSS Rule Tree)
- ?對CSS內容進行詞法分析、語法分析,解析CSS規則,構建CSS規則樹。
- ③ 渲染樹:DOM 樹 + CSS 規則樹,生成 渲染樹 (Render Tree)
- ?渲染樹只包含需要顯示的節點,及其樣式資訊,樣式資訊是來自CSS規則樹的樣式規則(CSS Rule)。
- ④ 佈局/迴流:根據渲染樹計算每一個節點的位置的過程,就是佈局。
- ?佈局(Layout):透過渲染樹中渲染物件的資訊,計算出每一個渲染物件的確切位置和尺寸,就是佈局的過程。HTML的佈局是自上而下、從左到右流式排列,位置是是會相互影響的,一個元素位置、大小變化會影響整體(其後續)佈局,導致迴流的發生。佈局的開銷是比較大的,要儘量避免頻繁佈局。
- ?迴流(Reflow):某個部分發生了變化影響了佈局,如DOM的新增、刪除,某個元素的位置尺寸發生了變化,那就需要倒回去重新佈局>渲染。
- ⑤ 渲染:根據計算好的資訊繪製頁面,透過呼叫作業系統Native GUI的API繪製,將呈現器的內容顯示在螢幕上。
- ?重繪(Repaint):某個元素的背景顏色,文字顏色的變化,不影響元素周圍或內部佈局,不需要重新佈局,就需只需要瀏覽器重繪即可。
06、有什麼啟示?-最佳化建議
使用者每次上網不就是在幹這個事情麼,輸入網址,等待網頁載入,檢視網頁內容,或者網頁載入太慢就咔嚓換一個,就是這麼無情。瞭解從URL輸入到頁面展現的詳細過程,可以更好幫助我們在各個環節去最佳化我們的WEB頁面。
- ① 提高連線速度:
- ?儘量合理控制網頁中資源的來源,如果來自很多個域名,如第三方、二級域名,每個域名都要DNS解析和建立TCP連線。
- ?不過上述方式需要根據實際情況來考慮,過多、過少都不一定就好,還得考慮瀏覽器的併發請求限制、資源型別、網路環境、終端裝置型別、CDN等。
- ?DNS預解析,提前解析域名獲得IP:
<link rel="dns-prefetch" href="//blog.poetries.top">
- ② 提高資源載入速度:
- ?減少請求次數:有些資源可以合併,如小圖片,CSS片段等。多利用快取,本地快取靜態資源。
- ?減少資源大小:圖片壓縮、資源壓縮(gzip),減少不必要的資源,按需載入等。
- ?啟用HTTP2,最佳化
header
,減少請求大小;多路複用,可並行請求響應。 - ?預載入與懶載入:預先載入一些需要用到的資源,延後載入一些非必須的資源。
- ③ 提高網頁解析、渲染速度:儘量減少迴流、重繪。
- ?避免頻繁操作DOM結構,及改變元素的大小、位置。
- 使用 transform 替代 top、left定位,transform只是DOM節點本身的變換,不影響佈局,就不會造成迴流。
- 少用table佈局,區域性的修改會造成整個table的重新佈局。
- 將JS放在body的最後面,可以避免資源阻塞,使靜態的HTML頁面儘快顯示。
- 注意防脫,注意遠離前端開發...
參考資料
©️版權申明:版權所有@安木夕,本文內容僅供學習,歡迎指正、交流,轉載請註明出處!原文編輯地址-語雀