1阔墩、 域名解析
2、 根據(jù)IP建立TCP連接(三次握手)
3蒲牧、 發(fā)送HTTP請求
4惦费、 服務器處理請求并返回HTTP報文
5、 瀏覽器解析并渲染頁面
6泰讽、 連接結(jié)束例衍,關(guān)閉TCP連接(四次揮手)
一、域名解析
當輸入一個域名的時候已卸,我們首先要做的就是將域名轉(zhuǎn)化成IP地址佛玄。前端的靜態(tài)資源等,都是存儲在服務器上咬最。在計算機網(wǎng)絡中翎嫡,我們不能通過域名直接訪問,只能通過IP地址訪問到具體的主機永乌。
①惑申、 轉(zhuǎn)換過程:
1、首先瀏覽器會查詢自身的緩存中翅雏,有沒有此條域名的解析圈驼,如果有的話,就返回這個解析后的地址望几。
2绩脆、如果瀏覽器自身的緩存中,沒有找到與此條域名對應的IP地址,那么就會去操作系統(tǒng)中的緩存中查找是否有這條域名的解析靴迫。
3惕味、如果在操作系統(tǒng)中也沒有找到的話,那么就需要通過DNS(域名系統(tǒng))幫助我們解析玉锌。
4名挥、DNS域名解析過程(詳細看參考鏈接)
②、可優(yōu)化策略:預先緩存當前頁面可能用到的域名到head里面
<link rel="dns-prefetch" href="xxx.com" />
二主守、 根據(jù)IP建立TCP連接(三次握手)
瀏覽器與遠程web服務器通過TCP三次握手協(xié)商來建立一個TCP/IP連接禀倔。該握手首先由客戶端嘗試建立起通信,而后服務器應答并接受客戶端的請求参淫,最后由客戶端發(fā)出該請求已經(jīng)被接受的報文救湖。
握手過程中使用了 TCP 的標志(flag) —— SYN(synchronize) 和 ACK(acknowledgement)。
- 發(fā)送端首先發(fā)送一個帶 SYN 標志的數(shù)據(jù)包給對方涎才。
- 接收端收到后鞋既, 回傳一個帶有 SYN/ACK 標志的數(shù)據(jù)包以示傳達確認信息。
- 最后憔维, 送端再回傳一個帶 ACK 標志的數(shù)據(jù)包涛救,代表“握手”結(jié)束。
若在握手過程中某個階段莫名中斷业扒,TCP 協(xié)議會再次以相同的順序發(fā)送相同的數(shù)據(jù)包检吆。
三、 發(fā)送HTTP請求
一旦TCP/IP連接建立程储,瀏覽器會通過該連接向遠程服務器發(fā)送HTTP請求蹭沛。
從上面兩圖中,看出瀏覽器的緩存過程:
1章鲤、首次訪問一個url摊灭,沒有緩存,但是服務器會響應一些header信息败徊,如:expires帚呼、cache-control、last-modified皱蹦、etag等煤杀,記錄下次請求是否緩存,如何緩存
2沪哺、再次訪問該url時沈自,瀏覽器會根據(jù)首次訪問返回的header信息,來決策是否緩存辜妓、如何緩存
①枯途、瀏覽器緩存機制分為強緩存忌怎、協(xié)商緩存:
當瀏覽器再次訪問某個url時,會先獲取資源的header信息酪夷,判斷是否命中強緩存:
1榴啸、如命中,直接從緩存獲取資源晚岭,包括響應的header信息(請求不會和服務器通信)插掂,也就是強緩存
2、如未命中強緩存腥例,瀏覽器發(fā)送請求到服務器,該請求會攜帶第一次請求返回的有關(guān)緩存的header信息酝润,由服務器根據(jù)請求種的相關(guān)header信息來對比結(jié)果是否協(xié)商緩存命中
1)若命中燎竖,服務器返回新的響應header信息,更新緩存中對應的header信息要销,但并不返回資源內(nèi)容构回,它會告訴瀏覽器可以直接從緩存獲取
2)否則疏咐,返回最新的資源內(nèi)容
②、強緩存和協(xié)商緩存的區(qū)別
緩存策略 | 獲取資源形式 | 狀態(tài)碼 | 發(fā)送請求到服務器 |
---|---|---|---|
強緩存 | 從緩存取 | 200(from memory cache) | 否浑塞,直接從緩存取 |
協(xié)商緩存 | 從緩存取 | 304(not modified) | 是,通過服務器來告知緩存是否可用 |
③酌壕、強緩存字段
Expires:Expires 的值是一個絕對時間的GMT格式的時間字符串(如Thu, 02 Sep 2021 11:03:45 GMT),在瀏覽器發(fā)起請求的時候卵牍,會根據(jù)系統(tǒng)時間和 Expires 的值進行比較,如果發(fā)送請求的時間在expires之前糊昙,那么本地緩存始終有效,否則就會發(fā)送請求到服務端來獲取資源释牺。
注:這個字段會導致一個問題,要是系統(tǒng)時間與服務器時間不一致的時候船侧,就可能出現(xiàn)假性失效,或者出現(xiàn)緩存已經(jīng)失效了镜撩,但是并未去請求最新資源
Cache-control:HTTP/1.1 中新增的屬性队塘,屬性值具有以下幾個:
- max-age:單位是秒,它是一個相對值宜鸯,計算方式是距離第一次響應頭中有該字段的時間憔古。如果時間超過,就要重新發(fā)起請求淋袖。
- no-cache:不使用本地緩存鸿市,需要使用緩存協(xié)商,每次都需要與服務器校驗文件的新鮮度
- no-store:直接禁止瀏覽器緩存數(shù)據(jù)即碗,每次用戶請求該資源焰情,都會向服務器發(fā)送一個請求,每次都會下載完整的資源剥懒。
- private:只能被終端用戶的瀏覽器緩存内舟。中間代理、cdn不能緩存此響應初橘。
- public:可用被所有的用戶緩存验游,包括終端用戶和cdn等中間代理服務器。
pragma:不使用強緩存保檐,需要驗證緩存是否新鮮耕蝉。(HTTP/1.1 之前版本的歷史遺留字段,僅作為與 HTTP/1.0 的向后兼容而定義)
注:如果cache-control和expires同時存在夜只,cache-control優(yōu)先(pragma > cache-control > expires)
③垒在、協(xié)商緩存字段
協(xié)商緩存都是由瀏覽器和服務器協(xié)商,來確定是否緩存盐肃,主要通過兩組header字段爪膊,兩組字段都是成對出現(xiàn)的,即第一次請求的響應頭上帶某個字段(Last-Modified 或 Etag)砸王,則后續(xù)請求會帶上對應的請求字段(if-modified-since或者if-none-match)推盛,若響應頭沒有,則請求頭也不會有對應的字段
-
Last-Modified/If-Moditied-Since
1)第一次請求谦铃,服務器響應頭返回Last-Modified耘成,表示該資源在服務器上的最后修改時間
2)再次請求,請求頭上加上If-Moditied-Since驹闰,即上一次請求時返回的Last-Modified值瘪菌。
3)再次請求中,根據(jù)瀏覽器傳過來的If-Moditied-Since和資源在服務器最后修改時間判斷嘹朗,資源是否有變化:
——>沒有變化师妙,返回304(NotModified),不返回資源內(nèi)容屹培,響應頭中也不會再添加Last-Modified(資源沒有變化怔檩,Last-Modified也不會改變)蓄诽。并且從緩存中加載資源
——>有變化,正常返回資源內(nèi)容乙埃,Last-Modified會被更新锯岖,下次請求時出吹,If-Moditied-Since會啟用上次返回的Last-Modified值。 -
Etag/If-Not-Match: 由服務器生成的每個資源的唯一標識字符串,只要資源有變化叫确,這兩個值就會改變芍锦;
1)判斷過程與Last-Modified娄琉、If-Moditied-Since類似,
2)與Last-Modified不同的是:當服務器返回304的響應時票腰,由于Etag重新生成過杏慰,響應頭還會把Etag返回炼鞠,即使Etag跟之前沒有變化。
注:Last-Modified可與Etag一起使用朝扼,Etag優(yōu)先
四擎颖、 服務器處理請求并返回HTTP報文
五、 瀏覽器解析并渲染頁面
1肖抱、過程如下:
①异旧、解析 HTML吮蛹,生成 DOM 樹(瀏覽器不能直接理解和使用HTML,需要將HTML轉(zhuǎn)換為瀏覽器能夠理解的結(jié)構(gòu))
②术荤、解析 CSS瓣戚,生成 CSS 規(guī)則樹
③焦读、合并 CSS 和 DOM 樹矗晃,生成render樹
④、計算渲染樹的布局(Layout/reflow)仓技,即各元素尺寸俗他、位置的計算
⑤兆衅、繪制 render 樹(paint),繪制頁面像素信息
⑥诉濒、瀏覽器將各層信息發(fā)送給GPU,GPU將各層合成未荒,顯示在屏幕
2片排、DOM 和 CSSOM的構(gòu)建過程
Bytes(字節(jié)) → characters(字符) → tokens(語義塊) → nodes(節(jié)點) → DOM(CSSOM構(gòu)建過程也一樣)
- conversion 轉(zhuǎn)換:瀏覽器將獲得的html內(nèi)容(Bytes)基于他的編碼轉(zhuǎn)換為單個字符(如果這個時候編碼方式跟文件的字節(jié)編碼不一致,便會出現(xiàn)亂碼迫卢。所以我們通過使用<meta http-equiv="content-type"content="text/html;charset=utf-8">來告訴瀏覽器我們頁面使用的是什么編碼乾蛤。)
- tokenizing分詞:瀏覽器按照html規(guī)范標準捅僵,將這些字符串轉(zhuǎn)換為不同的標記token庙楚,每個token都有自己獨特的含義以及規(guī)則集
- lexing詞法分析:分詞的結(jié)果是得到一堆的token,此時把他們轉(zhuǎn)為對象酪捡,這些對象分別定義他們的屬性和規(guī)則
- DOM構(gòu)建:因為html標記定義的就是不同標簽之間的關(guān)系沛善,這個關(guān)系就像樹形結(jié)構(gòu)一樣塞祈,比如body對象的父節(jié)點就是html對象议薪,然后p對象的父節(jié)點就是body對象
注:
1斯议、render樹的節(jié)點并不等同的dom樹的節(jié)點醇锚,因為有些節(jié)點的display為none,那么在生成render樹的時候恋昼,就不會將其加入到render樹中
2液肌、 當我們?yōu)g覽器獲得HTML文件后鸥滨,會自上而下的加載,并在加載過程中進行解析和渲染老速。
3、 如果在加載過程中遇到外部CSS文件和圖片额湘,瀏覽器會另外發(fā)送一個請求缩挑,去獲取CSS文件和相應的圖片鬓梅,這個請求是異步的,并不會影響HTML文件的加載芥丧。不會阻塞DOM樹的解析续担,會阻塞DOM樹的渲染和后面js語句的執(zhí)行活孩,當計算樣式的時候需要等待css文件的資源進行層疊樣式憾儒,資源阻塞了,會進行等待诗舰,直到網(wǎng)絡超時眶根,network報出錯誤,渲染進程繼續(xù)層疊樣式計算属百。為了避免讓用戶看到長時間的白屏時間诸老,應該提高css的加載速度:
- 使用cdn
- 對css進行壓縮
- 合理利用緩存
- 減少http請求,將多個css文件合并
4蹄衷、如果遇到Javascript文件愧口,HTML文件會掛起渲染的進程类茂,等待JavaScript文件加載完畢后,再繼續(xù)進行渲染厚骗。因為JavaScript可能會修改DOM领舰,導致后續(xù)HTML資源白白加載迟螺,所以HTML必須等待JavaScript文件加載完畢后矩父,再繼續(xù)渲染,這也就是為什么JavaScript文件在寫在底部body標簽前的原因
5民轴、 每個頁面至少需要一次回流后裸,就是在頁面第一次加載的時候辙售。
六旦部、 連接結(jié)束较店,關(guān)閉TCP連接(四次揮手)
1.第一次揮手:Client發(fā)送一個FIN,用來關(guān)閉Client到Server的數(shù)據(jù)傳送婚度,Client進入FIN_WAIT_1狀態(tài)官卡。
2.第二次揮手:Server收到FIN后,發(fā)送一個ACK給Client哮翘,確認序號為收到序號+1(與SYN相同,一個FIN占用一個序號)阻课,Server進入CLOSE_WAIT狀態(tài)限煞。
3.第三次揮手:Server發(fā)送一個FIN员凝,用來關(guān)閉Server到Client的數(shù)據(jù)傳送,Server進入LAST_ACK狀態(tài)硕舆。
4.第四次揮手:Client收到FIN后抚官,Client進入TIME_WAIT狀態(tài)阶捆,接著發(fā)送一個ACK給Server洒试,確認序號為收到序號+1, Server進入CLOSED狀態(tài)卒煞,完成四次揮手叼架。