突破瀏覽器域名併發限制的解決方案

卑微的前端發表於2019-12-31

背景

拿Chrome瀏覽器來說,同域名下資源載入的最大併發連線數為6,當資原始檔大於6時,多於6個的檔案就會進入待定,等第一批載入完才會載入第二批的6個圖片資源,這樣就增加了等待時間。無形中就增加使用者載入網頁等待的時間。

waiting.jpeg

思考

對於這種併發限制,可以有什麼方法來解決這種問題呢? 既然最大併發數為6,那我們就把N個資源URL替換成N/6個不同域名,這樣就有N/6個最大併發可以同時發生了。 先來看看我們處理前後的比對情況吧。

效果展示

本文拿圖片載入來舉例【具體的資源載入時間因不同裝置不同網速而不同,僅供參考】


處理前

當一個網頁的圖片資源在同一個域名情況下載入,如圖,30個圖片總用時【1.11s】

waitFinish.jpeg

最後一個圖片資源連線開始後的停轉時間(即圖片資源載入的等待響應時間)【357ms】

waitTime.png


處理後

同樣的執行環境,同樣的資源在多個域名(同一個ip)情況下載入,如圖,30個圖片總用時【424ms】

noWait.jpeg

最後一個圖片資源連線開始後的停轉時間【0.64ms】

noWaitTime.png


對比結果:在本示例中,同樣的資源,同一個IP,處理資源載入域名限制後,速度可以優化【60%】。用最後一張載入的圖片對比,連線開始後的停轉時間優化比也達到【99.8%】


實現方法

  • 實現思路

    • 在DNS服務商中申請多個域名,指向同一個 IP 服務。
    • 對後臺返回的資料進行域名處理,對圖片連結,進行域名替換。
    • 域名替換完成後,通過 localStorage 進行 key / value 儲存。以使得相同圖片在下一次展示時,能使用瀏覽器快取,而非重複載入。
  • 程式碼實現【本方法僅用在ajax回撥中】 =》 示例程式碼如下:

    	// 替換域名
        function replaceDomain(data) {
          let imgUrlObj = localStorage.getItem('imgUrlObj') || {} // 獲取本地儲存的圖片連結,能正常使用快取
          if (typeof(imgUrlObj) === 'string') { // 判斷是否為JSON物件,不是則轉換
            imgUrlObj = JSON.parse(imgUrlObj)
          }
          let index = Math.floor(Math.random() * 4.99) // 隨機0-4的下標
          try {
            data = JSON.stringify(data)
            data = data.replace(/www\.baidu\.com\/image(.*?)(jpg|png|jpeg)/g, (...params) => { // 查詢圖片的url並對其進行操作
              let sourceUrl = params[1] + params[2] // 圖片資源名稱,未包含域名。如:整條圖片連結為:www.baidu.com/image/123.png; 現儲存為:/image/123.png
              if (!imgUrlObj[sourceUrl]) { // 未儲存在本地,則新產生域名
                let imgUrl = `node${[1, 2, 3, 4, 5][index % 5]}.baidu.com/image/${sourceUrl}` // 域名替換,如:從 www.baidu.com 替換到 node1.baidu.com,node2.baidu.com
                imgUrlObj[sourceUrl] = imgUrl // 同時儲存好新的域名,在這就體現了使用JSON物件的好處,圖片資源路徑名當key值,圖片完整連結當value值
                localStorage.setItem('imgUrlObj', JSON.stringify(imgUrlObj))
                index++
                return imgUrl
              } else { // 儲存到了本地,則直接使用localStorage的url
                return imgUrlObj[sourceUrl]
              }
            })
            data = JSON.parse(data)
          } catch (e) {
            console.log('replaceDomain error')
            console.log(e)
          }
          return data
        }
    複製程式碼
  • 另外,為了加快DNS解析,可以進行DNS預載入

    <!-- 配置 Mate 進行域名預載入 -->
    <!-- dns預載入 -->
    <link rel="dns-prefetch" href="//node1.baidu.com" />
    <link rel="dns-prefetch" href="//node2.baidu.com" />
    複製程式碼

完結,撒花

shuai.jpeg

相關文章