【前端性能優化指南】2 - 加快請求速度

更多前端性能優化系列請點擊這裏 >>前端

在前一部分,咱們介紹了瀏覽器緩存。當一個請求走過了各級前端緩存後,就會須要實際發送一個請求了。git

在 HTTP 緩存中,咱們其實也有發送請求;或者是在 HTTP/2 Push 下,使用了以前鏈接中推送的資源。不過爲了保證思路的連貫,我仍是把「發送請求」這個章節總體放在「緩存」以後了。github

介紹網絡請求其實能夠包含複雜的網絡知識。不過,今天我們的旅程主要聚焦於「前端性能優化」。所以,主要會介紹一些在這個環節中,前端性能優化可能會作的事兒。web

1. 避免多餘重定向

重定向是一個比較經常使用的技術手段。在一些狀況下,你可能進行了服務遷移,修改了原有的 uri。這時候就可使用重定向,把訪問原網址的用戶重定向到新的 uri。還有是在一些登陸場景下,會使用到重定向技術。算法

重定向分爲 301 的永久重定向和 302 的臨時重定向。建議貼合語義,例如服務遷移的狀況下,使用 301 重定向。對 SEO 也會更友好。chrome

同時也不要濫用重定向。曾今也見過有業務在訪問後重定向 3 次的狀況,其實裏面有些是沒必要要的。每次重定向都是有請求耗時的,建議避免過多的重定向。跨域

2. DNS 預解析

基本咱們訪問遠程服務的時候,不會直接使用服務的出口 IP,而是使用域名。因此請求的一個重要環節就是域名解析。瀏覽器

DNS 服務自己是一個樹狀層級結構,其解析是一個遞歸與迭代的過程。例如 github.com 的大體解析流程以下:緩存

  1. 先檢查本地 hosts 文件中是否有映射,有則使用;
  2. 查找本地 DNS 緩存,有則返回;
  3. 根據配置在 TCP/IP 參數中設置 DNS 查詢服務器,並向其進行查詢,這裏先稱爲本地 DNS;
  4. 若是該服務器沒法解析域名(沒有緩存),且不須要轉發,則會向根服務器請求;
  5. 根服務器根據域名類型判斷對應的頂級域名服務器(.com),返回給本地 DNS,而後重複該過程,直到找到該域名;
  6. 固然,若是設置了轉發,本地 DNS 會將請求逐級轉發,直到轉發服務器返回或者也不能解析。

更詳細的介紹能夠看這篇文章[1]性能優化

這裏咱們須要瞭解的是:

  • 首先,DNS 解析流程可能會很長,耗時很高,因此整個 DNS 服務,包括客戶端都會有緩存機制,這個做爲前端很差涉入;
  • 其次,在 DNS 解析上,前端仍是能夠經過瀏覽器提供的其餘手段來「加速」的。

DNS Prefetch[2] 就是瀏覽器提供給咱們的一個 API。它是 Resource Hint 的一部分。它能夠告訴瀏覽器:過會我就可能要去 yourwebsite.com 上下載一個資源啦,幫我先解析一下域名吧。這樣以後用戶點擊某個按鈕,觸發了 yourwebsite.com 域名下的遠程請求時,就略去了 DNS 解析的步驟。使用方式很簡單:

<link rel="dns-prefetch" href="//yourwebsite.com">
複製代碼

固然,瀏覽器並不保證必定會去解析域名,可能會根據當前的網絡、負載等情況作決定。標準裏也明確寫了👇

user agent SHOULD resolve as early as possible

3. 預先創建鏈接

咱們知道,創建鏈接不只須要 DNS 查詢,還須要進行 TCP 協議握手,有些還會有 TLS/SSL 協議,這些都會致使鏈接的耗時。使用 Preconnect[3] 能夠幫助你告訴瀏覽器:「我有一些資源會用到某個源(origin),你能夠幫我預先創建鏈接。」

根據規範,當你使用 Preconnect 時,瀏覽器大體作了以下處理:

  • 首先,解析 Preconnect 的 url;
  • 其次,根據當前 link 元素中的屬性進行 cors 的設置;
  • 而後,默認先將 credential 設爲 true,若是 cors 爲 Anonymous 而且存在跨域,則將 credential 置爲 false
  • 最後,進行鏈接。

使用 Preconnect 只須要將 rel 屬性設爲 preconnect 便可:

<link rel="preconnect" href="//sample.com">
複製代碼

固然,你也能夠設置 CORS:

<link rel="preconnect" href="//sample.com" crossorigin>
複製代碼

須要注意的是,標準並無硬性規定瀏覽器必定要(而是 SHOULD)完成整個鏈接過程,與 DNS Prefetch 相似,瀏覽器能夠視狀況完成部分工做。

4. 使用 CDN

當咱們實際把網絡包發向咱們的目標地址時,確定但願越快到達目的地越好(對應的,也會但願越快得到響應)。而網絡傳輸是有極限的,一樣一個北京的用戶,訪問北京的服務器顯然要比廣州快不少。同時,服務的負載也會影響響應的速度。

對於靜態資源,咱們能夠考慮經過 CDN 來下降時延。

對於使用 CDN 的資源,DNS 解析會將 CDN 資源的域名解析到 CDN 服務的負載均衡器上,負載均衡器能夠經過請求的信息獲取用戶對應的地理區域,從而經過負載均衡算法,在背後的諸多服務器中,綜合選擇一臺地理位置近、負載低的機器來提供服務。例如爲北京聯通用戶解析北京的服務器 IP。這樣,用戶在以後訪問 CDN 資源時都是訪問北京服務器,距離近,速度快。

想了解更多 CDN 的工做方式能夠閱讀這篇文章[4]


下圖是請求聲明週期中各個階段的示意圖,能夠幫助咱們理解發送請求(以及接收響應)的流程。


在緩存無法知足咱們的狀況下,就要開始真正發送請求了。從前端性能優化視角,咱們會關注重定向、DNS 解析等問題,從而加速請求。但這塊還預留了一小部分 —— 服務端的處理與響應。

過去,咱們會將前端侷限在瀏覽器中,可是隨着 NodeJS 的興起,不少業務都引入了基於 NodeJS 的 BFF 來爲前端(客戶端端)提供服務。因此我們此次的旅程也會簡單聊一下,在這一階段能夠作的一些優化。


目前內容已所有更新至 ✨ fe-performance-journey ✨ 倉庫中,陸續會將內容同步到掘金上。若是但願儘快閱讀相關內容,能夠直接去該倉庫中瀏覽文章。

喜歡的朋友能夠 star 一下,後續也會繼續更新更多性能優化相關的內容。


參考資料

  1. DNS 的解析過程
  2. Resource Hints - DNS Prefetch
  3. Resource Hints - Preconnect
  4. CDN 之我見:原理篇
  5. Understanding Resource Timing
  6. TCP 3-Way Handshake Process
  7. TCP 4 wave hands
  8. 圖文還原HTTPS原理
  9. URL redirection (wikipedia)
相關文章
相關標籤/搜索