輸入url按回車後發生的一系列不可描述的事情
前言
最近在研究如何優化首屏白屏時間,大致分為網路部分和js渲染部分,該文章主要是梳理一下從輸入url開始,從客戶端到服務端會發生哪些事情,從哪些地方可以做優化。
過程圖
瀏覽器輸入url後發生的過程
1、輸入一個url地址
url遵守一定的語法規則:scheme://host.domain:port/path/filename
- scheme:定義因特網服務的型別(協議),常見的有http,https,file,ftp等
- host:定義域主機(http一般預設的是www)
- demain:定義因特網域名,如baidu.com
- post:埠號(http一般是80,https一般是443)
2、瀏覽器會先檢視瀏覽器快取--系統快取--路由快取,如有存在快取,就直接顯示。如果沒有,接著第三步
3、瀏覽器查詢域名的ip地址(DNS,域名和ip的對映分散式資料庫)
大致可以分為幾部:
-
瀏覽器快取
瀏覽器會快取DNS記錄一段時間,且不同的瀏覽器的快取時間不同
-
系統快取
如果在瀏覽器快取裡沒有找到需要的記錄,瀏覽器會做一個系統呼叫(windows裡是gethostbyname)。這樣便可獲得系統快取(host)中的記錄。
-
路由器快取
查詢請求發向路由器,它一般會有自己的DNS快取。
-
ISP DNS 快取
ISP是網際網路服務提供商(Internet Service Provider)的簡稱,ISP有專門的DNS伺服器應對DNS查詢請求。
-
根伺服器(遞迴搜尋)
ISP的DNS伺服器還找不到的話,它就會向根伺服器發出請求,進行遞迴查詢(DNS伺服器先問根域名伺服器其的IP地址,然後再問.com域名伺服器,依次類推)
CDN(Content Delivery Network)就是利用DNS的重定向技術,DNS伺服器會返回一個跟使用者最接近的點的IP地址給使用者,CDN節點的伺服器負責響應使用者的請求,提供所需的內容。
針對DNS的優化大致方向是減少DNS解析的時間,即儘量通過瀏覽器對dns的快取機制來減少對ip的查詢,即減少需要解析的域名的個數
4、瀏覽器給web伺服器傳送一個HTTP(HTTPS)請求
-
TCP三次握手
瀏覽器獲得 IP 地址後,就會對目標伺服器發起建立 TCP 連線的請求,建立連線主要有三個步驟,一般稱為客戶端與伺服器端的三次握手:
第一次握手: 建立連線時,客戶端傳送syn包(syn=j)到伺服器,並進入SYN_SENT狀態,等待伺服器確認;
第二次握手: 伺服器收到syn包,必須確認客戶的SYN(ack=j+1),同時自己也傳送一個SYN包(syn=k),即SYN+ACK包,此時伺服器進入SYN_RECV狀態;
第三次握手: 客戶端收到伺服器的SYN+ACK包,向伺服器傳送確認包ACK(ack=k+1),此包傳送完畢,客戶端和伺服器進入ESTABLISHED(TCP連線成功)狀態,完成三次握手。
-
TCP四次揮手
客戶端或伺服器均可主動發起揮手動作
第一次揮手: 主動關閉方,將FIN置為1,Seq設定為Z為上一次對方傳送過來的Ack值,Ack設定為X為Seq值+1。設定好以上值後,將資料傳送至被動關閉方(這裡標記為:B)。然後A進入FIN_WAIT_1狀態。
第二次揮手:B收到了A傳送的FIN報文段,向A回覆,Ack設定為第一次揮手中的Seq值+1,Seq設定為Y第一次揮手中的Ack值。然後B進入CLOSE_WAIT狀態,A收到B的回覆後,進入FIN_WAIT_2狀態。
第三次揮手:B再次向A傳送報文,將FIN置為1,Ack設定為X,Seq設定為Y。然後B進入LAST_ACK狀態,A收到B的報文後,進入TIME_WAIT狀態。
第四次揮手:A收到B傳送的FIN報文段,Ack設定為Y,Seq設定為X。然後A進入TIME_WAIT狀態,B在收到報文後進入CLOSED狀態,A在傳送完報文等待了2MSL時間後進入CLOSED狀態。
-
HTTPS(http+ssl)的非對稱加密和對稱加密
-
非對稱加密
握手過程中,伺服器會發出一張證書(帶著公鑰),客戶端用公鑰加密了一段較短的資料S,並返回給伺服器。伺服器用私鑰解開,拿到S。此時,握手步驟完成,S成為了一個被安全傳輸到對方手中的對稱加密金鑰。此後,伺服器與請求響應,只需要用S作為金鑰進行一次對稱的加密就好。
證書包含公鑰,所以拿到證書意味著就拿到了對方的公鑰
-
對稱加密
約定加密金鑰,請求的資料用金鑰加密,伺服器用金鑰解密
一次完整的https請求:
1、客戶端向伺服器傳送https請求(443埠)
2、tcp三次握手建立tcp連線
2、伺服器端返回一個安全證書(公鑰)
3、客戶端收到,並進行驗證,如果沒有問題,就用安全證書(公鑰)加密一個隨機值。併發送給服務端
4、服務端用私鑰解密,拿到該隨機值
5、後面的通訊就可以通過隨機值用對稱加密的方式進行了
-
-
http預設自帶cookie
在http請求中,cookie是預設自帶的,可以通過設定cookie的HttpOnly和Secure屬性來進行控制,詳情請移步
-
請求頭自帶的與tcp相關的屬性
-
Connection
Connection 頭(header) 決定當前的事務完成後,是否會關閉網路連線。如果該值是“keep-alive”,網路連線就是持久的,不會關閉,使得對同一個伺服器的請求可以繼續在該連線上完成。
在http1.0的時候Connection的值預設為close
在http1.1的時候Connection的值預設為Keep-Alive
-
-
瀏覽器會自發做的事
瀏覽器能安全的新增斜槓,如www.baidu.com ->www.baidu.com/ ,而www.baidu.com/222 ->www.baidu.com/222不會,因為瀏覽器…
優化 :
- 通過部署cdn來減緩資料返回的事件
- 優化握手次數
- 在頭部設定Accept-Encoding型別,通過返回gzip來減少資料體積
- 通過設定http快取來優化效能,請移步
5、永久重定向響應
為了優化搜尋引擎,把多個域名進行歸類,如把baidu.com,www.baidu.com,www.baidu.com歸類 返回301,通知瀏覽器跳轉,有利於SEO
6、瀏覽器跟蹤重定向地址,請求頭不變
7、伺服器“處理”請求
8、伺服器發回一個HTML響應
9、瀏覽器開始顯示HTML
- 處理HTML標記,構建DOM樹。
- 處理CSS標記,構建CSSOM樹。
- 將DOM樹和CSSOM樹融合成渲染樹(會忽略不需要渲染的dom)。
- 根據渲染樹來佈局,計算每個節點的幾何資訊。
- 在螢幕上繪製各個節點。
- 中間遇到各種資源時,會進行資源的下載
可能存在問題:
-
資源下載
-
css下載時會阻塞渲染(帶有media屬性除外,不會阻塞瀏覽器解析)。
-
遇到 script 標籤時,DOM構建停止,此時控制權移交至js,直到指令碼(下載)執行完畢,此時瀏覽器有優化一般會下載其他資源,但是不會解析。如果js中有對CSSOM的操作,還會先確保CSSOM已經被下載並構建。
-
圖片資源下載不會產生阻塞。
-
-
重繪重排導致重新進行渲染樹的生成
-
重排(迴流)
會重新計算佈局,通常由元素的結構、增刪、位置、尺寸變化引起,如:img下載成功後,替換填充頁面img元素,引起尺寸變化;也會由js的屬性值讀取引起,如讀取offset、scroll、cilent、getComputedStyle等資訊。
-
重繪
簡單外觀的改變會引起重繪,如顏色變化等。
-
重排一定重繪。
-
優化:
- dom
-
簡化dom結構,減少DOM樹和渲染樹構建成本,減少頁面元素個數
如使用列表表格資料分頁,簡單表格不要使用複雜第三方元件等方式。
-
- js
-
將js指令碼標籤放在頁面body底部,減少對其他過程的阻塞。
延遲執行:對不修改頁面的外鏈script使用defer屬性,使指令碼並行下載不阻塞,下載後不立刻執行,而在所有元素解析之後執行。
這裡簡單的介紹下defer和async的區別:
相同點:
- 載入檔案時不阻塞頁面渲染
- 對於inline的script(內聯指令碼)無效
- 使用這兩個屬性的指令碼中不能呼叫document.write方法
- 有指令碼的onload的事件回撥
不同點:
- html的版本html4.0中定義了defer;html5.0中定義了async
- 每一個async屬性的指令碼都在它下載結束之後立刻執行,可能會打亂原有的順序
- 每一個defer屬性的指令碼都是在頁面解析完畢之後,按照原本的順序執行
-
減少和合並不必要的dom相關操作,如使用DocumentFragment、修改classname而不是各項style等,減少對重繪和重排的觸發。
-
- css
- 將css放入head中,提前載入,並防止html渲染後重新結合css引起頁面閃爍。
- 減少css層級和css選擇器複雜度,提高解析速度,雖然瀏覽器有優化。
- 使用更高效能的css樣式,如flex代替float。
- 開啟複合層,如使用3d變換、opacity等,使該元素及其子元素不導致外部的重排,但是也有坑。
- 合理使用脫離文件流的樣式,減少對外部重排的影響,如absolute。
- 檔案數量
-
減少首次下載的檔案數量大小.
使用圖片懶載入,js的按需載入等方式,使用storage儲存進行js、css檔案的快取(PWA)。
-
拆分頁面資源,首屏資料優先載入等。
動態路由、懶載入
-
10、瀏覽器傳送獲取嵌入在HTML中的靜態資源 11、瀏覽器傳送非同步(AJAX)請求
簡單的介紹下fetch相對於ajax的優缺點
- 優點
- 內建promise,鏈式呼叫,也可以使用async await來解決回撥地獄
- res提供了多種轉換格式的方法,json(),blob()
- 缺點
- 預設不帶cookie,帶cookie需要指定credentials = include
- 需要底層支援,或者使用第三方相容包
- 不能做超時處理,沒有abort方法
- 遇到常見的錯誤碼不會報錯,需要手動去封裝
最後
推薦一下自己的個人公眾號:前端每日精讀(每日定時推送一篇前端好文)