從輸入U(xiǎn)RL到頁面加載發(fā)生了什么

(非原創(chuàng),)

1. DNS解析

DNS解析的過程就是尋找哪臺機(jī)器上有你需要資源的過程。當(dāng)你在瀏覽器中輸入一個(gè)地址時(shí),例如www.baidu.com,其實(shí)不是百度網(wǎng)站真正意義上的地址?;ヂ?lián)網(wǎng)上每一臺計(jì)算機(jī)的唯一標(biāo)識是它的IP地址,但是IP地址并不方便記憶。用戶更喜歡用方便記憶的網(wǎng)址去尋找互聯(lián)網(wǎng)上的其它計(jì)算機(jī),也就是上面提到的百度的網(wǎng)址。所以互聯(lián)網(wǎng)設(shè)計(jì)者需要在用戶的方便性與可用性方面做一個(gè)權(quán)衡,這個(gè)權(quán)衡就是一個(gè)網(wǎng)址到IP地址的轉(zhuǎn)換,這個(gè)過程就是DNS解析。它實(shí)際上充當(dāng)了一個(gè)翻譯的角色,實(shí)現(xiàn)了網(wǎng)址到IP地址的轉(zhuǎn)換.

2. 瀏覽器向 web 服務(wù)器發(fā)送一個(gè) HTTP 請求

拿到域名對應(yīng)的IP地址之后,瀏覽器會以一個(gè)隨機(jī)端口(1024<端口<65535)向服務(wù)器的WEB程序(常用的有httpd,nginx等)80端口發(fā)起TCP的連接請求。這個(gè)連接請求到達(dá)服務(wù)器端后(這中間通過各種路由設(shè)備,局域網(wǎng)內(nèi)除外),進(jìn)入到網(wǎng)卡,然后是進(jìn)入到內(nèi)核的TCP/IP協(xié)議棧(用于識別該連接請求,解封包,一層一層的剝開),還有可能要經(jīng)過Netfilter防火墻(屬于內(nèi)核的模塊)的過濾,最終到達(dá)WEB程序,最終建立了TCP/IP的連接。

3. 服務(wù)器的永久重定向響應(yīng)

服務(wù)器給瀏覽器響應(yīng)一個(gè)301永久重定向響應(yīng),這樣瀏覽器就會訪問“http://www.google.com/” 而非“http://google.com/”。為什么服務(wù)器一定要重定向而不是直接發(fā)送用戶想看的網(wǎng)頁內(nèi)容呢?其中一個(gè)原因跟搜索引擎排名有關(guān)。如果一個(gè)頁面有兩個(gè)地址,就像http://www.yy.com/和http://yy.com/,搜索引擎會認(rèn)為它們是兩個(gè)網(wǎng)站,結(jié)果造成每個(gè)搜索鏈接都減少從而降低排名。而搜索引擎知道301永久重定向是什么意思,這樣就會把訪問帶www的和不帶www的地址歸到同一個(gè)網(wǎng)站排名下。還有就是用不同的地址會造成緩存友好性變差,當(dāng)一個(gè)頁面有好幾個(gè)名字時(shí),它可能會在緩存里出現(xiàn)好幾次。

4. 瀏覽器跟蹤重定向地址

現(xiàn)在瀏覽器知道了 "http://www.google.com/"才是要訪問的正確地址,所以它會發(fā)送另一個(gè)http請求。這里沒有啥好說的

5. 服務(wù)器處理請求

經(jīng)過前面的重重步驟,我們終于將我們的http請求發(fā)送到了服務(wù)器這里,其實(shí)前面的重定向已經(jīng)是到達(dá)服務(wù)器了,那么,服務(wù)器是如何處理我們的請求的呢?

后端從在固定的端口接收到TCP報(bào)文開始,它會對TCP連接進(jìn)行處理,對HTTP協(xié)議進(jìn)行解析,并按照報(bào)文格式進(jìn)一步封裝成HTTP Request對象,供上層使用。

一些大一點(diǎn)的網(wǎng)站會將你的請求到反向代理服務(wù)器中,因?yàn)楫?dāng)網(wǎng)站訪問量非常大,網(wǎng)站越來越慢,一臺服務(wù)器已經(jīng)不夠用了。于是將同一個(gè)應(yīng)用部署在多臺服務(wù)器上,將大量用戶的請求分配給多臺機(jī)器處理。此時(shí),客戶端不是直接通過HTTP協(xié)議訪問某網(wǎng)站應(yīng)用服務(wù)器,而是先請求到Nginx,Nginx再請求應(yīng)用服務(wù)器,然后將結(jié)果返回給客戶端,這里Nginx的作用是反向代理服務(wù)器。同時(shí)也帶來了一個(gè)好處,其中一臺服務(wù)器萬一掛了,只要還有其他服務(wù)器正常運(yùn)行,就不會影響用戶使用。通過Nginx的反向代理,我們到達(dá)了web服務(wù)器,服務(wù)端腳本處理我們的請求,訪問我們的數(shù)據(jù)庫,獲取需要獲取的內(nèi)容等等,當(dāng)然,這個(gè)過程涉及很多后端腳本的復(fù)雜操作。由于對這一塊不熟,所以這一塊只能介紹這么多了。

6. 服務(wù)器返回一個(gè) HTTP 響應(yīng)

經(jīng)過前面的6個(gè)步驟,服務(wù)器收到了我們的請求,也處理我們的請求,到這一步,它會把它的處理結(jié)果返回,也就是返回一個(gè)HTPP響應(yīng)。

HTTP響應(yīng)與HTTP請求相似,HTTP響應(yīng)也由3個(gè)部分構(gòu)成,分別是:

l 狀態(tài)行

l 響應(yīng)頭(Response Header)

l 響應(yīng)正文

HTTP/1.1200OKDate: Sat,31Dec200523:59:59GMT Content-Type: text/html;charset=ISO-8859-1Content-Length:122

<html> <head> <title>http</title> </head> <body> <!-- body goes here --> </body> </html>

狀態(tài)行:

狀態(tài)行由協(xié)議版本、數(shù)字形式的狀態(tài)代碼、及相應(yīng)的狀態(tài)描述,各元素之間以空格分隔。

格式: HTTP-Version Status-Code Reason-Phrase CRLF

例如: HTTP/1.1 200 OK rn

--協(xié)議版本:是用http1.0還是其他版本

--狀態(tài)描述:狀態(tài)描述給出了關(guān)于狀態(tài)代碼的簡短的文字描述。比如狀態(tài)代碼為200時(shí)的描述為 ok

--狀態(tài)代碼:狀態(tài)代碼由三位數(shù)字組成,第一個(gè)數(shù)字定義了響應(yīng)的類別,且有五種可能取值。如下

1xx:信息性狀態(tài)碼,表示服務(wù)器已接收了客戶端請求,客戶端可繼續(xù)發(fā)送請求。

100 Continue

101 Switching Protocols

2xx:成功狀態(tài)碼,表示服務(wù)器已成功接收到請求并進(jìn)行處理。200 OK 表示客戶端請求成功

204 No Content 成功,但不返回任何實(shí)體的主體部分

206 Partial Content 成功執(zhí)行了一個(gè)范圍(Range)請求

3xx:重定向狀態(tài)碼,表示服務(wù)器要求客戶端重定向。

301 Moved Permanently 永久性重定向,響應(yīng)報(bào)文的Location首部應(yīng)該有該資源的新URL

302 Found 臨時(shí)性重定向,響應(yīng)報(bào)文的Location首部給出的URL用來臨時(shí)定位資源

303 See Other 請求的資源存在著另一個(gè)URI,客戶端應(yīng)使用GET方法定向獲取請求的資源

304 Not Modified 服務(wù)器內(nèi)容沒有更新,可以直接讀取瀏覽器緩存

307 Temporary Redirect 臨時(shí)重定向。與302 Found含義一樣。302禁止POST變換為GET,但實(shí)際使用時(shí)并不一定,307則更多瀏覽器可能會遵循這一標(biāo)準(zhǔn),但也依賴于瀏覽器具體實(shí)現(xiàn)

4xx:客戶端錯(cuò)誤狀態(tài)碼,表示客戶端的請求有非法內(nèi)容。

400 Bad Request 表示客戶端請求有語法錯(cuò)誤,不能被服務(wù)器所理解

401 Unauthonzed 表示請求未經(jīng)授權(quán),該狀態(tài)代碼必須與 WWW-Authenticate 報(bào)頭域一起使用

403 Forbidden 表示服務(wù)器收到請求,但是拒絕提供服務(wù),通常會在響應(yīng)正文中給出不提供服務(wù)的原因

404 Not Found 請求的資源不存在,例如,輸入了錯(cuò)誤的URL

5xx:服務(wù)器錯(cuò)誤狀態(tài)碼,表示服務(wù)器未能正常處理客戶端的請求而出現(xiàn)意外錯(cuò)誤。

500 Internel Server Error 表示服務(wù)器發(fā)生不可預(yù)期的錯(cuò)誤,導(dǎo)致無法完成客戶端的請求

503 Service Unavailable 表示服務(wù)器當(dāng)前不能夠處理客戶端的請求,在一段時(shí)間之后,服務(wù)器可能會恢復(fù)正常

7. 瀏覽器顯示 HTML

在瀏覽器沒有完整接受全部HTML文檔時(shí),它就已經(jīng)開始顯示這個(gè)頁面了,瀏覽器是如何把頁面呈現(xiàn)在屏幕上的呢?不同瀏覽器可能解析的過程不太一樣,這里我們只介紹webkit的渲染過程,下圖對應(yīng)的就是WebKit渲染的過程,這個(gè)過程包括:

解析html以構(gòu)建dom樹 -> 構(gòu)建render樹 -> 布局render樹 -> 繪制render樹

瀏覽器在解析html文件時(shí),會”自上而下“加載,并在加載過程中進(jìn)行解析渲染。在解析過程中,如果遇到請求外部資源時(shí),如圖片、外鏈的CSS、iconfont等,請求過程是異步的,并不會影響html文檔進(jìn)行加載。

解析過程中,瀏覽器首先會解析HTML文件構(gòu)建DOM樹,然后解析CSS文件構(gòu)建渲染樹,等到渲染樹構(gòu)建完成后,瀏覽器開始布局渲染樹并將其繪制到屏幕上。這個(gè)過程比較復(fù)雜,涉及到兩個(gè)概念: reflow(回流)和repain(重繪)。

DOM節(jié)點(diǎn)中的各個(gè)元素都是以盒模型的形式存在,這些都需要瀏覽器去計(jì)算其位置和大小等,這個(gè)過程稱為relow;當(dāng)盒模型的位置,大小以及其他屬性,如顏色,字體,等確定下來之后,瀏覽器便開始繪制內(nèi)容,這個(gè)過程稱為repain。

頁面在首次加載時(shí)必然會經(jīng)歷reflow和repain。reflow和repain過程是非常消耗性能的,尤其是在移動設(shè)備上,它會破壞用戶體驗(yàn),有時(shí)會造成頁面卡頓。所以我們應(yīng)該盡可能少的減少reflow和repain。

當(dāng)文檔加載過程中遇到j(luò)s文件,html文檔會掛起渲染(加載解析渲染同步)的線程,不僅要等待文檔中js文件加載完畢,還要等待解析執(zhí)行完畢,才可以恢復(fù)html文檔的渲染線程。因?yàn)镴S有可能會修改DOM,最為經(jīng)典的document.write,這意味著,在JS執(zhí)行完成前,后續(xù)所有資源的下載可能是沒有必要的,這是js阻塞后續(xù)資源下載的根本原因。所以我明平時(shí)的代碼中,js是放在html文檔末尾的。

JS的解析是由瀏覽器中的JS解析引擎完成的,比如谷歌的是V8。JS是單線程運(yùn)行,也就是說,在同一個(gè)時(shí)間內(nèi)只能做一件事,所有的任務(wù)都需要排隊(duì),前一個(gè)任務(wù)結(jié)束,后一個(gè)任務(wù)才能開始。但是又存在某些任務(wù)比較耗時(shí),如IO讀寫等,所以需要一種機(jī)制可以先執(zhí)行排在后面的任務(wù),這就是:同步任務(wù)(synchronous)和異步任務(wù)(asynchronous)。

JS的執(zhí)行機(jī)制就可以看做是一個(gè)主線程加上一個(gè)任務(wù)隊(duì)列(task queue)。同步任務(wù)就是放在主線程上執(zhí)行的任務(wù),異步任務(wù)是放在任務(wù)隊(duì)列中的任務(wù)。所有的同步任務(wù)在主線程上執(zhí)行,形成一個(gè)執(zhí)行棧;異步任務(wù)有了運(yùn)行結(jié)果就會在任務(wù)隊(duì)列中放置一個(gè)事件;腳本運(yùn)行時(shí)先依次運(yùn)行執(zhí)行棧,然后會從任務(wù)隊(duì)列里提取事件,運(yùn)行任務(wù)隊(duì)列中的任務(wù),這個(gè)過程是不斷重復(fù)的,所以又叫做事件循環(huán)(Event loop)。

8. 瀏覽器發(fā)送請求獲取嵌入在 HTML 中的資源(如圖片、音頻、視頻、CSS、JS等等)

其實(shí)這個(gè)步驟可以并列在步驟8中,在瀏覽器顯示HTML時(shí),它會注意到需要獲取其他地址內(nèi)容的標(biāo)簽。這時(shí),瀏覽器會發(fā)送一個(gè)獲取請求來重新獲得這些文件。比如我要獲取外圖片,CSS,JS文件等,類似于下面的鏈接:

圖片:

CSS式樣表:http://static.ak.fbcdn.net/rsrc.php/z448Z/hash/2plh8s4n.css

Java 文件:http://static.ak.fbcdn.net/rsrc.php/zEMOA/hash/c8yzb6ub.js

這些地址都要經(jīng)歷一個(gè)和HTML讀取類似的過程。所以瀏覽器會在DNS中查找這些域名,發(fā)送請求,重定向等等...

不像動態(tài)頁面,靜態(tài)文件會允許瀏覽器對其進(jìn)行緩存。有的文件可能會不需要與服務(wù)器通訊,而從緩存中直接讀取,或者可以放到CDN中

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容