前言:“一個頁面從輸入 URL 到頁面加載顯示完成,這個過程中都發生了什么?” 這個問題我想大多數人都不會陌生,好像是前端面試題經常會出現的,在此我也好好梳理梳理了一番,總結成這篇文章,希望能對和我一樣在前端道路上奮進的小白們有所幫助,一起學習,交流。
我把這個問題拆解成兩個過程:
1. 用戶輸入 url ---> 客戶端(瀏覽器)拿到服務端的數據
2. 瀏覽器拿到數據 ---> 呈現頁面(也就是瀏覽器工作過程)
搞清楚這兩個過程后,我們也算是完整的回答了前言部分所提的問題了。
一. 輸入網址到瀏覽器獲得資源的過程
舉個例子:
1. 輸入網址: http://www.cnblogs.com/dinghuihua/p/6674719.html
把url分成協議、網絡地址、資源路徑三部分
- 協議:從該計算機獲取資源的方式,有HTTP、HTTPS、FTP等,不同協議有不同的通訊內容格式
- 網絡地址:指連接網絡上的哪一台計算機,可以是域名、IP地址,可以包括端口號。如:“www.cnblogs.com”、“192.168.0.91:8080”
- 資源路徑:指從服務器上獲取哪一項資源。如 “/dinghuihua/p/6674719.html”
2. 通過DNS解析獲得網址的對應IP地址
當發送一個url請求時,不管這個url是web頁面的url還是web頁面上的每個資源的url,瀏覽器都會開啟一個線程處理該請求,同時在遠程DNS服務器上啟動一個DNS查詢,這能使瀏覽器獲得請求對應的IP地址
PS: 腦補為啥有DNS這玩意...因為要人類記住辣么多計算機能記住的IP地址怎么可能嘛...它就是起到域名解析的作用的
dns是將域名和IP進行綁定的,通過域名找到互聯網上實際的物理地址的服務器,找到這個服務器后,服務器會把請求解析,找到該文件(上下文)后將其推送給瀏覽器, 瀏覽器就會把這個html文件通過它自己的瀏覽器內核定義好的規范解析渲染出來(渲染:呈現元素)
這一步包括DNS的具體查找過程
- 瀏覽器緩存 – 瀏覽器會緩存DNS記錄一段時間。 有趣的是,操作系統沒有告訴瀏覽器儲存DNS記錄的時間,這樣不同瀏覽器會儲存個自固定的一個時間(2分鍾到30分鍾不等)。
- 系統緩存 – 如果在瀏覽器緩存里沒有找到需要的記錄,瀏覽器會做一個系統調用(windows里是gethostbyname)。這樣便可獲得系統緩存中的記錄。
- 路由器緩存 – 接着,前面的查詢請求發向路由器,它一般會有自己的DNS緩存。
- ISP DNS 緩存 – 接下來要check的就是ISP緩存DNS的服務器。在這一般都能找到相應的緩存記錄。
- 遞歸搜索 – 你的ISP的DNS服務器從跟域名服務器開始進行遞歸搜索,從.com頂級域名服務器到Facebook的域名服務器。一般DNS服務器的緩存中會有.com域名服務器中的域名,所以到頂級服務器的匹配過程不是那么必要了。
3. 瀏覽器與遠程web服務器 通過TCP三次握手協商來建立一個 TCP/IP 連接
該握手包括一個“同步報文”,一個“同步-應答報文”和一個“應答報文”,這三個報文在 瀏覽器和服務器之間傳遞。該握手首先由客戶端嘗試建立起通信,而后服務器應答並接受客戶端的請求,最后由客戶端發出該請求已經被接受的報文。
4. 瀏覽器 通過TCP/IP連接 向web服務器 發送一個 HTTP 請求
5. 服務器的永久重定向響應(從 http://example.com 到 http://www.example.com)
6. 瀏覽器跟蹤重定向地址
7. 服務器處理請求
8. 服務器返回一個 HTTP 響應
遠程服務器找到要請求的資源並使用 HTTP 響應返回該資源,值為 200 的 HTTP 響應狀態表示一個正確的響應。
9. 到這里便是瀏覽器的工作過程了。。。
瀏覽器顯示 HTML
瀏覽器發送請求獲取嵌入在 HTML 中的資源(如圖片、音頻、視頻、CSS、JS等等)
瀏覽器發送異步請求
二. 瀏覽器獲得資源后到呈現頁面的過程
常用的瀏覽器有很多,有IE、Firefox、Safari、Chrome以及Opera,還有很多國產瀏覽器,像360瀏覽器啊這些,它們的存在共同點都是為了讓用戶看到各種各樣的網站,它們不同的是內核的不同,因此可能會給前端工程師們帶來一些瀏覽器的差異性兼容性問題。
* 瀏覽器主要的功能:通過向服務器請求,來獲取你所想要的網絡資源,並將它渲染到瀏覽器窗口中。而資源類型通常是html文件,但也可能是PDF,圖片或者是其他類型的資源。
* 瀏覽器的內核(渲染引擎)有:
user agent : 代表瀏覽器內核,不特指哪個瀏覽器
瀏覽器內核 | 廠商前綴 | 代表瀏覽器 | 內核背景 |
Trident | -ms- | IE瀏覽器系列 | 該內核程序在1997年的IE4中首次被采用,是微軟在Mosaic代碼的基礎之上修改而來的,並沿用到IE11,也被普遍稱作”IE內核”。Trident實際上是一款開放的內核,其接口內核設計的相當成熟,因此才有許多采用IE內核而非IE的瀏覽器(殼瀏覽器)涌現。 |
Gecko | -moz- | Firefox | Netscape6開始采用的內核,后來的Mozilla FireFox(火狐瀏覽器)也采用了該內核,Gecko的特點是代碼完全公開 |
Webkit | -webkit- | Safari | Safari內核,Chrome內核原型,開源,包含了來自KDE項目和蘋果公司的一些組件,主要用於Mac OS系統,它的特點在於源碼解構清晰、渲染速度極快,缺點是網頁代碼的兼容性不高,導致一些編寫不標准的網頁無法正常顯示 |
Blink | -webkit- | Chrome、opera等除IE、Firefox、Safari之外的幾乎所有瀏覽器(幾乎所有國產雙內核瀏覽器(Trident/Blink)如360、獵豹、qq、百度等) | Blink是一個由Google和Opera Software開發的瀏覽器排版引擎,是基於Webkit內核的子項目 |
Presto | -o- | Opera前內核[現已廢棄] | Opera12.17及更早版本曾經采用的內核,現已停止開發並廢棄 |
其實瀏覽器拿到資源數據后,便開始瀏覽器渲染引擎的基本渲染流程
渲染引擎開始解析HTML文檔,並把標簽轉化成內容樹中的DOM節點。同時它也開始解析樣式數據,外鏈的css文件以及style標簽內的樣式。所有這些樣式數據以及HTML中的可見性指令都是用來創建另一棵樹--render 樹。
現在頁面就呈現在我們面前了。。。
我看到有其他關於這個問題的解釋,也挺完善的,截個圖補充補充。。。
擴展:因為有這么個過程,所以我們就可以在不同時期干不同事情。頁面加載完成有兩種事件:
執行順序
- ready,表示文檔結構(DOM結構)已經加載完成(不包含圖片等非文字媒體文件),
- onload,指示頁面包含圖片等文件在內的所有元素都加載完成
$(function(){ // do something }); // 其實這個就是jQuery ready()的簡寫,他等價於: $(document).ready(function(){ //do something }) // 或者如下的寫法,因為jQuery 的默認參數是:“document”; $().ready(function(){ //do something })
多函數加載的問題
因為js沒有重載,所以后面的函數會覆蓋前面的同名函數
<body onload="a();b()"> </body>
(1). body中聲明的onload事件(DOM0級別)會被后面的window.onlad()(DOM0級別)覆蓋
<body onload="a();b()"> </body> <script> window.onload = function(){
alert('world');
} </script>
結果只彈出“world”
(2). 可以在body的onload中實現多函數執行
<body onload="a();b()"> </body> <srcipt> function a(){alert('a');} function b(){alert('b');} </script>
結果分別彈出“a”和“b”
(3). 多個window.onload()會產生覆蓋
window.onload = function(){alert('hello');} window.onload = function(){alert('world');}
結果只會彈出“world”
(4). 用jQuery的話,可以用多個load函數實現,它們會按順序依次執行
$(window).load(function() { alert("hello"); }); $(window).load(function() { alert("world"); });
相關知識補充:
1. http狀態碼有哪些?
- 1xx 【消息】服務器收到請求,需要請求者繼續執行操作
- 2xx 【成功】請求已成功被服務器接收、理解、並接受。
- 3xx 【重定向】客戶端需要采取進一步的操作以完成請求
- 4xx 【客戶端請求錯誤】客戶端錯誤,請求包含語法錯誤或無法完成請求
- 5xx 【服務器錯誤】服務器在處理請求的過程中發生了錯誤
常見的有:
- 200 OK //客戶端請求成功
- 304 Not Modified // 未修改。所請求的資源未修改,服務器返回此狀態碼時,不會返回任何資源
- 400 Bad Request //客戶端請求有語法錯誤,不能被服務器所理解
- 401 Unauthorized // 當前請求要求用戶的身份認證
- 403 Forbidden // 服務器理解請求客戶端的請求,但是拒絕執行此請求
- 404 Not Found //請求資源不存在,輸入了錯誤的URL
- 500 Internal Server Error //服務器發生不可預期的錯誤
- 503 Server Unavailable // 由於超載或系統維護,服務器暫時的無法處理客戶端的請求。一段時間后可能恢復正常
更多可見:http://www.webmasterhome.cn/httpstatus/
2. TCP三次握手:
3. TCP/IP協議族
- 這個協議族是規定我們瀏覽器和服務器之間的通信規則的。
- 網絡的分層:
(1).應用層 應用層指的是瀏覽器和服務器
協議:HTTP協議
(2).傳輸層 將發送的數據拆包
協議:TCP協議、 UPD協議
(3).網絡層 負責發送文件
協議:IP協議
(4).數據鏈路層 網路中接口,硬件層
4. HTTP協議 ---> 超文本傳輸協議
- HTTP協議就是規定瀏覽器和服務器之間通信的報文的格式。
- 報文的整體格式:
報文首部 - 首部又分成了兩個部分: 1.報文首行 2.報文頭
空行
報文體