Dns-prefetch DNS 预解析优化页面加载速度
浏览器访问一个链接时并不是直接将请求到网页对应的服务器上,而是先要做域名解析——将域名解析到网页对应的服务器 ip 地址,然后浏览器才能和服务器之间建立起通信交互,其过程大致如下图所示:
做域名解析就要访问域名服务器(在没有缓存缓存的情况下),这就会出现网路开销,开销的大小新取决于你的 dns 服务器和你的距离,一般要要几十毫秒到几百毫秒之间,请求的域名比较少的时候可能对用户来说无感知,单请求的域名多了,尤其是请求之间有先后顺序,那延迟就比较明显了。一般的大型网站,资源都是分开存储的,一个页面上请求十几个域名是常有的事情。好在浏览器比较聪明,会把 dns 解析结果缓存一段时间(谷歌浏览器可以通过chrome://net-internals/#dns
查看浏览器缓存的 dns 解析结果),以减少相同域名的再次解析。但用户第一次访问你的页面,或者长时间没有访问你的页面,都会重新请求 dns 服务器来解析域名。
dns-prefetch(dns 预解析)指令可以在尚未访问 url 的时候提前做 dns 解析(和其他 url 请求并行执行),从而在真正请求 url 的时候避免对 dns 服务器的解析,进而达到加速网页加载的目的。
在 Chrome 中默认已经开启对静态资源的 dns 预解析,因为页面下载到浏览器时已经知道需要访问哪些静态资源 url,所以浏览器会提前做 dns 预解析操作。但对于通过 js 动态加载的 url,浏览器就不会自动预解析了,这时 dns-prefetch 就会派上明显的用场。我们举一个例子,看下真实的效果:
function load(tag, url) {
var node = document.createElement(tag);if ('link' == tag) {node.type = "text/css"; node.rel = "stylesheet"; node.href = url;} else {node.src = url;}document.body.append(node);}setTimeout(function(){load('link', '///bootstrap/4.0.0-alpha.5/css/bootstrap-flex.min.css');load('script', '///bootstrap/4.0.0-alpha.5/js/bootstrap.min.js');load('link', '///bootstrap/3.1.1/css/bootstrap.min.css');load('script', '///bootstrap/3.1.1/js/bootstrap.min.js');load('link', '///bootstrap/3.3.7/css/bootstrap.min.css');load('script', '///bootstrap/3.3.7/js/bootstrap.min.js');load('link', '///ajax/libs/twitter-bootstrap/4.0.0-alpha.5/css/bootstrap.min.css');load('script', '///ajax/libs/twitter-bootstrap/4.0.0-alpha.5/js/bootstrap.min.js');}, 2000);
使用 dns-prefetch 的代码:
<!DOCTYPE html>
<html lang="zh-CN"><head><meta http-equiv="x-dns-prefetch-control" content="off"></head><body><script src="dynamic_load_res.js"></script></body></html>
x-dns-prefetch-control
表示手动关闭 dns-prefetch 功能。
我们通过/的测试截图如下:
使用 dns-prefetch 的代码(不要忘记加//
):
<!DOCTYPE html>
<html lang="zh-CN"><head><link rel="dns-prefetch" href="//"><link rel="dns-prefetch" href="//"><link rel="dns-prefetch" href="//"><link rel="dns-prefetch" href="//"></head><body><script src="dynamic_load_res.js"></script></body></html>
效果截图如下:
从图中可见,dns 解析大幅提前到加载资源之前了。真正加载资源文件时就不用再次请求 dns 服务器了。