当浏览器请求一个 URL 的时候大概有以下几个过程:阻挡、域名解析、建立连接、发送请求、等待响应、接收数据。一般取决于用户的网络情况和网站服务器处理速度有关。
<meta charset="utf-8" />
<meta http-equiv="x-dns-prefetch-control" content="on">
<link rel="dns-prefetch" href="//qintia.com">
<link rel="dns-prefetch" href="//www.qintia.com">
阻挡:不同的浏览器对单个域名的最大并发连接数有一定的限制,HTTP/1.0 和 HTTP/1.1 也不相同。比如 HTTP/1.1 协议下,IE6 的并发连接数限制是 2 个;而在 HTTP/1.0 下,IE6 的并发连接数可以达到 4 个。在其它浏览器也有类似的限制,一般是 4~8 个。这个时候,如果浏览器同时对某一域名发起多个请求,超过了限制就会出现等待,也就是阻挡。
那么为了解决阻挡这一问题,我们可以对某些 URL 的域名分散处理,比如我们的图片域名,一般用类似 img.hexingxing.cn 的域名,当一个页面包含 20 多张图片的时候,那至少有 10 几个请求会被阻挡,而如果我们分散到 img0.hexingxing.cn/img1.hexingxing.cn/img2.hexingxing.cn/…等不同域名的时候,至少这 20 个图片请求会并发进行,网站打开速度会明显提升很多。类似的,可以对一些 CSS 和 JS 的域名同样处理。
域名解析:从域名查询 IP 的过程,这个过程一般都很快的,但也会引起延迟。一般浏览器会适当的对解析结果缓存,并对页面中出现的新域名进行预解析,但并不是所有的浏览器都会这么做,为了帮助其它浏览器对某些域名进行预解析,你可以在页面的 html 标签中添加 dns-prefetch 告诉浏览器对指定域名预解析:
<link rel="dns-prefetch" href="//domain.com">
一般大型网站都会看到此类配置,以下是常见大型网站的 DNS 预解析配置信息:
<link rel="dns-prefetch" href="//s1.bdstatic.com"/>
<link rel="dns-prefetch" href="//t1.baidu.com"/>
<link rel="dns-prefetch" href="//t2.baidu.com"/>
<link rel="dns-prefetch" href="//t3.baidu.com"/>
<link rel="dns-prefetch" href="//t10.baidu.com"/>
<link rel="dns-prefetch" href="//t11.baidu.com"/>
<link rel="dns-prefetch" href="//t12.baidu.com"/>
<link rel="dns-prefetch" href="//b1.bdstatic.com"/>
<link rel="dns-prefetch" href="//static.360buyimg.com"/>
<link rel="dns-prefetch" href="//misc.360buyimg.com"/>
<link rel="dns-prefetch" href="//img10.360buyimg.com"/>
<link rel="dns-prefetch" href="//img11.360buyimg.com"/>
<link rel="dns-prefetch" href="//img12.360buyimg.com"/>
<link rel="dns-prefetch" href="//img13.360buyimg.com"/>
<link rel="dns-prefetch" href="//img14.360buyimg.com"/>
<link rel="dns-prefetch" href="//img20.360buyimg.com"/>
<link rel="dns-prefetch" href="//img30.360buyimg.com"/>
<link rel="dns-prefetch" href="//d.3.cn"/>
<link rel="dns-prefetch" href="//d.jd.com"/>
<link rel="dns-prefetch" href="//g.alicdn.com" />
<link rel="dns-prefetch" href="//img.alicdn.com" />
<link rel="dns-prefetch" href="//tce.alicdn.com" />
<link rel="dns-prefetch" href="//gm.mmstat.com" />
<link ref="dns-prefetch" href="//tce.taobao.com" />
<link rel="dns-prefetch" href="//log.mmstat.com" />
<link rel="dns-prefetch" href="//tui.taobao.com" />
<link rel="dns-prefetch" href="//ald.taobao.com" />
<link rel="dns-prefetch" href="//gw.alicdn.com" />
<link rel="dns-prefetch" href="//atanx.alicdn.com"/>
<link rel="dns-prefetch" href="//dfhs.tanx.com"/>
<link rel="dns-prefetch" href="//ecpm.tanx.com" />
<link rel="dns-prefetch" href="//res.mmstat.com" />
那就是为什么用 g.alicdn.com 这个域名,而不是 g.taobao.com 呢?这个得从 cookie 说起,淘宝的 cookie 已经非常大了,据说曾接近 1K,如果用后面的域名,那每次请求图片都会带上长长的 cookie,后果可想而知,不仅使得网络请求变慢,而且还浪费了带宽,而淘宝图片服务器并不需要这些 cookie。这就是所说的 cookie 污染,为了解决这一问题,单独的域名是很有必要的。
DNS 预解析是浏览器试图在用户访问链接之前解析域名,这是计算机的正常 DNS 解析机制。域名解析后,如果用户确实访问该域名,那么 DNS 解析时间将不会有延迟。
最明显的例子,DNS 预解析在某个页面中包含非常多的域名非常有效,如搜索结果页。遇到网页中的超链接,DNS prefetching 从中提取域名并将其解析为 IP 地址,这些工作在用户浏览网页时,使用最少的 CPU 和网络在后台进行解析。当用户点击这些已经预解析的域名,可以平均减少 200 毫秒耗时(假设用户最近还未访问过该域名),更重要的是用户不会遇到 DNS 解析最坏的情况(往往超过 1 秒)。
DNS Prefetch,即 DNS 预获取,是前端优化的一部分。一般来说,在前端优化中与 DNS 有关的有两点: 1. 减少 DNS 的请求次数 2. 进行 DNS 预获取
DNS 作为互联网的基础协议,其解析的速度似乎很容易被网站优化人员忽视。现在大多数新浏览器已经针对 DNS 解析进行了优化,典型的一次 DNS 解析需要耗费 20-120 毫秒,减少 DNS 解析时间和次数是个很好的优化方式。 DNS Prefetching 是让具有此属性的域名不需要用户点击链接就在后台解析,而域名解析和内容载入是串行的网络操作,所以这个方式能 减少用户的等待时间,提升用户体验。浏览器对网站第一次的域名 DNS 解析查找流程依次为:浏览器缓存——系统缓存——路由器缓存——ISP DNS 缓存——递归搜索。
默认情况下浏览器会对页面中和当前域名(正在浏览网页的域名)不在同一个域的域名进行预获取,并且缓存结果,这就是隐式的 DNS Prefetch。如果想对页面中没有出现的域进行预获取,那么就要使用显示的 DNS Prefetch。
5.1. 用 meta 信息来告知浏览器, 当前页面要做 DNS 预解析:
<meta http-equiv="x-dns-prefetch-control" content="on" />
5.2. 在页面 header 中使用 link 标签来强制对 DNS 预解析:
<link rel="dns-prefetch" href="http://x1.hexingxing.cn" />
5.3. 如果需要禁止隐式的 DNS Prefetch,可以使用以下的标签:
<meta http-equiv="x-dns-prefetch-control" content="off">