當我們在瀏覽器地址欄中輸入網址時,頁面會很快展現出來,這其中到底發生了什么?
總的來說分為如下幾個過程:
1.輸入url
2.域名解析
3.服務器處理請求
4.瀏覽器解析渲染頁面
1.輸入url
什么是url?
URL(Uniform Resource Locator),統一資源定位符,用于定位互聯網上的資源,實際上就是網站網址。url的格式一般為:
協議類型://<主機名>:<端口>/<路徑>/文件名
其中協議類型可以是http(超文本傳輸協議)、https、ftp(文件傳輸協議)、telnet(遠程登錄協議)、file等等。而http是最常見的網絡傳輸協議,https則是進行加密的網絡傳輸。
例如,以http://www.lxweimin.com/u/hello.jpg,其中,“http”表示與web服務器通訊采用http協議,簡書web服務器域名為www.lxweimin.com,u/hello.jpg表示所訪問的文件存在于web服務器上的路徑。
IP是什么?
IP是因特網中的每臺連接到網絡的計算機為實現相互通信而遵循的規則協議。每個處于互聯網中的設備都有IP 地址,形如 192.168.0.1,而127.0.0.1代表本機的 IP。IP又分為局域網IP和公網IP。而局域網 IP 和公網 IP 是有差別的。每個網站就是靠IP來定位的。
為了便于記憶或辨識,人們使用域名來登錄網站,每個域名背后有對應的IP地址。
比如對于http://www.lxweimin.com的URL,瀏覽器實際上不知道www.lxweimin.com到底是什么東西,需要查找www.lxweimin.com網站所在服務器的IP地址,才能找到目標,這就是下文要說的域名解析即DNS解析。
2.DNS解析
DNS充當了一個翻譯的角色,實現了網址到實際ip地址的轉換,那么它是如何進行轉換的,
過程如下,
當用戶在瀏覽器中輸入url后,你使用的電腦會發出一個DNS請求到本地DNS服務器。本地DNS服務器一般都是你的網絡接入服務器商提供,比如中國電信,中國移動,DNS請求到達本地DNS服務器之后會有以下幾個步驟:
1.本地 DNS服務器將該請求轉發到互聯網上的根域(根域沒有名字,在DNS系統中就用一個空字符串來表示。例如www.baidu.com.現在的DNS系統都不會要求域名以.來結束,即www.baidu.com就可以解析了,但是現在很多DNS解析服務商還是會要求在填寫DNS記錄的時候以.來結尾域名。
2.根域將所要查詢域名中的頂級域(比如要查詢www.baidu,com,該域名的頂級域就是com)的服務器IP地址返回到本地DNS。
3.本地DNS根據返回的IP地址,再向頂級域(就是com域)發送請求, com域服務器再將域名中的二級域(即www.baidu.com中的baidu.com)的IP地址返回給本地DNS。
4.本地DNS再向二級域發送請求進行查詢。
5.之后不斷重復這樣的過程,直到本地DNS服務器得到最終的查詢結果,并返回到主機。這時候主機才能通過域名訪問該網站。
DNS優化
如果每次都經過這么多步驟,是否太耗時間?如何減少該過程的步驟呢?那就是DNS緩存。
DNS緩存
DNS存在著多級緩存,從離瀏覽器的距離排序的話,有以下幾種: 瀏覽器緩存,系統緩存,路由器緩存,IPS服務器緩存,根域名服務器緩存,頂級域名服務器緩存,主域名服務器緩存。
3.服務器處理請求
當瀏覽器得到相應的ip地址之后,會向服務器發送http請求,我們的web-server收到請求之后,會響應請求http? response,有可能響應的就是一個HTML文本,來讓瀏覽器可以瀏覽。
4.瀏覽器解析渲染頁面
瀏覽器在收到HTML,CSS,JS文件后,它是如何把頁面呈現到屏幕上的?下圖對應的就是WebKit渲染的過程。
瀏覽器是一個邊解析邊渲染的過程。首先瀏覽器解析HTML文件構建DOM樹,然后解析CSS文件構建渲染樹,等到渲染樹構建完成后,瀏覽器開始布局渲染樹并將其繪制到屏幕上。這個過程比較復雜,涉及到兩個概念: reflow(回流)和repain(重繪)。DOM節點中的各個元素都是以盒模型的形式存在,這些都需要瀏覽器去計算其位置和大小等,這個過程稱為relow;當盒模型的位置,大小以及其他屬性,如顏色,字體,等確定下來之后,瀏覽器便開始繪制內容,這個過程稱為repain。頁面在首次加載時必然會經歷reflow和repain。reflow和repain過程是非常消耗性能的,尤其是在移動設備上,它會破壞用戶體驗,有時會造成頁面卡頓。所以我們應該盡可能少的減少reflow和repain。
JS的解析是由瀏覽器中的JS解析引擎完成的。JS是單線程運行,也就是說,在同一個時間內只能做一件事,所有的任務都需要排隊,前一個任務結束,后一個任務才能開始。但是又存在某些任務比較耗時,如IO讀寫等,所以需要一種機制可以先執行排在后面的任務,這就是:同步任務(synchronous)和異步任務(asynchronous)。JS的執行機制就可以看做是一個主線程加上一個任務隊列(task queue)。同步任務就是放在主線程上執行的任務,異步任務是放在任務隊列中的任務。所有的同步任務在主線程上執行,形成一個執行棧;異步任務有了運行結果就會在任務隊列中放置一個事件;腳本運行時先依次運行執行棧,然后會從任務隊列里提取事件,運行任務隊列中的任務,這個過程是不斷重復的,所以又叫做事件循環(Event loop)。
瀏覽器在解析過程中,如果遇到請求外部資源時,如圖像,iconfont,JS等。瀏覽器將重復1-6過程下載該資源。請求過程是異步的,并不會影響HTML文檔進行加載,但是當文檔加載過程中遇到JS文件,HTML文檔會掛起渲染過程,不僅要等到文檔中JS文件加載完畢還要等待解析執行完畢,才會繼續HTML的渲染過程。原因是因為JS有可能修改DOM結構,這就意味著JS執行完成前,后續所有資源的下載是沒有必要的,這就是JS阻塞后續資源下載的根本原因。CSS文件的加載不影響JS文件的加載,但是卻影響JS文件的執行。JS代碼執行前瀏覽器必須保證CSS文件已經下載并加載完畢。