背景
拿Chrome瀏覽器來說,同域名下資源載入的最大併發連線數為6,當資原始檔大於6時,多於6個的檔案就會進入待定,等第一批載入完才會載入第二批的6個圖片資源,這樣就增加了等待時間。無形中就增加使用者載入網頁等待的時間。
思考
對於這種併發限制,可以有什麼方法來解決這種問題呢? 既然最大併發數為6,那我們就把N個資源URL替換成N/6個不同域名,這樣就有N/6個最大併發可以同時發生了。 先來看看我們處理前後的比對情況吧。
效果展示
本文拿圖片載入來舉例【具體的資源載入時間因不同裝置不同網速而不同,僅供參考】
處理前
當一個網頁的圖片資源在同一個域名情況下載入,如圖,30個圖片總用時【1.11s】
最後一個圖片資源連線開始後的停轉時間(即圖片資源載入的等待響應時間)【357ms】
處理後
同樣的執行環境,同樣的資源在多個域名(同一個ip)情況下載入,如圖,30個圖片總用時【424ms】
最後一個圖片資源連線開始後的停轉時間【0.64ms】
對比結果:在本示例中,同樣的資源,同一個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" /> 複製程式碼