背景
拿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" />
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。