從瀏覽器原理分析界面性能優化01

從瀏覽器原理分析界面性能優化—瀏覽器的網絡請求

衆所周知,當我們在瀏覽器的地址欄輸入一個域名並且回車後,瀏覽器就能夠進行網絡請求,然後將我們想要的界面展示出來.
但是這個過程瀏覽器到底經歷了什麼,我們又可以怎樣進行優化,這是我們今天要討論的問題

瀏覽器運行過程

我們都知道,在多進程瀏覽器架構的模式下,從輸入 URL 到發起網絡請求是需要多個進程的配合的.
我們先看一下瀏覽器進程和網絡進程的作用:

  • 瀏覽器進程:負責進程調度,用戶交互,數據存儲等功能
  • 網絡進程:提供網絡服務下載功能

爲了簡單明瞭,先附一張簡單的流程圖

在這裏插入圖片描述

用戶輸入 URL

當我們輸入一段信息之後,瀏覽器會先判斷我們輸入的是一段搜索信息還是一個URL.

  • 如果是搜索信息,瀏覽器會使用默認的搜索引擎,合成帶由搜索關鍵字的 URL
  • 如果是 URL 瀏覽器會添加上網絡協議,將其合成爲一個完整的 URL

用戶點擊回車

當我們輸入 URL,瀏覽器處理完畢,這個時候我們點擊回車意味着我們同意將當前界面替換成新的界面.瀏覽器開始繼續工作

瀏覽器在離開當前頁面之前回調用 beforeunload 方法,我們來看一下 MDN 上對該方法的描述

事件使網頁能夠觸發一個確認對話框,詢問用戶是否真的要離開該頁面。如果用戶確認,瀏覽器將導航到新頁面,否則導航將會取消
根據規範,要顯示確認對話框,在事件處理上需要調用 preventDefault()

該事件的主要作用就是提示用戶是否離開當前界面,當我們確認離開當前界面以後,瀏覽器就開始進行網絡請求了

網絡進程的處理

當處理完 beforeunload 之後,瀏覽器會將處理過後的 URL 通過進程間通信(IPC)發送給網絡進程,網絡進程收到 URL 以後會發起真正的網絡請求過程.
主要分以下幾步:

查找本地緩存

網絡進程會先查找本地是否緩存了資源,如果有緩存資源,那麼該請求返回200,並把相應資源返回給瀏覽器進程,
PS: 有一點需要注意的是,這裏的緩存指的是強緩存
如果沒有命中強緩存的話,則會進行下一步的 DNS 解析

DNS 解析

DNS 解析的目的是通過域名去獲取服務器的 IP 地址和對應的端口號,如果沒有端口號,那麼 http 協議默認是 80 端口,https 協議默認是 443 端口,如果請求是 HTTPS 協議,還需要建立 TSL 連接
PS:DNS 解析也是會先檢查之前有沒有緩存過該域名的 IP 地址的,如果能夠命中緩存則直接返回緩存內容,否則去請求本地域名服務器進行後續的操作

DNS 解析完成後我們就獲得了該 URL 的 IP 地址,下面就可以進行真正的網絡請求了

與服務器建立連接傳輸數據

這個過程是通過 IP 地址與服務器建立連接
需要注意的是,在 Chrome 瀏覽器中,同一域名下最多建立 6 個 TCP 連接,超過這個數量,後續的連接將會進入等待狀態,等待前面的 TCP 連接釋放後才能夠建立新的連接.
我們現將網絡大致看作應用層、傳輸層、網絡層,那麼數據的傳輸可以大致分爲下面幾步

  • TCP 三次握手建立連接
  • 應用層中的 HTTP 協議生成針對目標的 Web 服務器的 HTTP 請求報文(同時也負責對接收到的網絡內容做處理)
  • 傳輸層中的 TCP 協議將 HTTP 請求報文按序號分割成報文段,添加上目標程序端口號和源端口號(同時,在接收請求過程中他也負責將報文段按照順序拼接成一個完成的報文)
  • 網絡層中的 IP 在數據包中添加上 IP 頭部(包括目標 IP 和源 IP)
  • 當請求通過物理層的中轉傳輸到達對方服務器後,服務器通過逆向的上述流程解析請求數據
  • 如果需要重定向,服務器返回相應的狀態碼(301、302、303 等),同時在 Location 字段附上相應的重定向地址,瀏覽器會根據狀態碼和地址進行重定向操作
  • 如果不是重定向,服務器會檢查是否命中協商緩存(協商緩存中的 Etag 優先級要高於 LostModify,但是兩者各有優劣,是互補關係),如果命中協商緩存,則服務器返回 304 和空的請求體
  • 如果沒有命中協商緩存,則服務器處理請求,返回 200 和相應的資源
  • 客戶端按照網絡層=>傳輸層=>應用層的順序開始接收數據

網絡進程的處理

到了接收數據的這一步,網絡進程會將獲取的數據包進行解析,然後通過響應頭中的 Content-type 字段判斷數據類型,如果是字節流的類型,則將接收到的數據交給下載管理器,該導航結束,不再進行
如果是 text/html 等的類型,就通過瀏覽器進程獲取到文檔準備開始下一步的渲染工作

以上,就是從我們輸入 URL 到界面顯示過程中的網絡請求部分,在這個部分中我們可以看到,佔比重最大的就是網路進程中的網絡請求部分了,那麼我們下面來看一下我們可以從什麼地方就行優化

優化的思路

HTTP 優化的方向由兩個(關於緩存問題,放到後面瀏覽器緩存部分):

  • 減少請求次數
  • 減少單次請求所花費的時間

其實,上面兩個方向已經包含在關鍵渲染路徑(CRP)裏面了,這也是我們講到性能優化的時候繞怎麼也不開的一個話題.
關鍵渲染路徑主要包括三部分:

  • 關鍵資源數量
  • 關鍵路徑長度
  • 關鍵字節數

上面的關鍵資源數量,其實就可以看作是減少網絡請求次數,關鍵字節數和關鍵路徑長度即可以簡單的歸類爲減少了單次請求花費的時間.

減少請求次數

在 HTTP1.1 的環境下,我們如果想減少請求的次數,大概可以有以下選擇:

  • 適當的使用內聯的 CSS 和 JS,避免過多的腳本文件的請求
  • 使用 async/defer 或者 preload/prefetch 對文件進行異步加載(這個在後面的瀏覽器渲染流程文章中會有討論)
  • 對於小型圖片的話可以使用 Sprite 圖,進行圖片的合併.(在 HTTP2.0 的情況下需要另行討論)

減少單次請求所花費的時間

壓縮文件體積和管線化

單次請求花費的時間,我們可以從兩方面着手,一方面是壓縮文件的體積,另一方面是使用持久鏈接或者管線化的方式進行通信.
PS:在 HTTP1.1 中是默認開啓持久鏈接的,但是在 HTTP1.1 之前的版本默認鏈接都是非持久鏈接.所以,如果你想在舊版本的 HTTP 協議上使用持久鏈接,需要指定請求頭的 Connection 爲 Keep-Alive

使用 http 壓縮

減少單次請求的時間也可以使用GZip

gzip 是由文件壓縮程序 gzip(GUN zip)生成的編碼格式採用 Lempel-Ziv 算法及 32 位循環冗餘校驗
deflate:組合使用 zlib 格式及由 deflate 雅座算法生成的編碼格式

我們可以通過請求中的Accept-Encoding:,來告訴服務器用戶代理支持的內容編碼以及內容編碼優先級順序,例如Accept-Encoding:gzip,deflate,就是告訴服務器,瀏覽器支持 gzip 和 delate 兩種格式的壓縮,這個時候服務器可以傳輸給我們 gzip 或者 deflate 壓縮格式的數據了
使用 gzip 可以壓縮我們的數據節省好多流量,也是一種減少單次請求時間的方式

壓縮文件的體積

我們可以使用 Webpack 對我們的文件進行壓縮和搖樹的操作,去掉空白行、回車符、默認註釋等.
同時,我們網站中圖片的選擇也是一個重中之重的問題,不同格式的圖片的大小和質量是不同的.這也是一個質量和加載速度之間的權衡.我們後面的文章中會有提到,不同的圖片對加載速度和質量的影響.這裏先佔個坑.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章