Pre-fetching会提示浏览器那些未来一定或可能使用到的资源,有时在当前页面见效,有些则在未来可能打开的页面生效。 作为开发者,我们比浏览器更懂自己的应用。我们可以利用这些技术提前告知浏览器web中用到的核心资源。
实际上可以拆分成很多小点:dns-prefetch, subresource, prefetch, preconnect, 和 prerender.
DNS prefetch
DNS prefetching通过指定具体的URL来告知客户端未来会用到相关的资源,这样浏览器可以尽早的解析DNS。比如我们需要一个在example.com的图片或者视频文件。在<head>就可以这么写:
<link rel="dns-prefetch"href="//example.com">
Harry Roberts在他的前端性能优化文章中建议:
简单的一行就能让支持的浏览器提前解析DNS。也就是说在浏览器请求资源时,DNS查询就已经准备好了。
Preconnect
和DNS prefetch类似,preconnect不光会解析DNS,还会建立TCP握手连接和TLS协议(如果需要)。用法如下:
<link rel="preconnect" href="http://css-tricks.com">
现代浏览器竭尽所能的尝试预测网站可能需要哪些链接。通过提前连接,浏览器可以提前建立必要的通信,消除了实际请求中DNS、TCP和TLS的耗时。不过,即使是只能的现代浏览器,也没办法为每个网站可靠的预测所有连接。
幸运的是开发者可以告诉浏览器哪些通信需要在实际请求发起前就提前建立连接。
例: 上半张图显示了浏览器先拉html、再拉CSS并建立好CSSOM后,发现需要两个外链的字体(在fonts.gstatic.com上),然后浏览器开始发起两个请求,具体来说,需要对这个域进行DNS解析、TCP和TLS握手(一个建立后可以复用给另一个连接)。
<link href='https://fonts.gstatic.com' rel='preconnect'crossorigin>
<link href='https://fonts.googleapis.com/css?family=Roboto+Slab:700|Open+Sans' rel='stylesheet'>
Subresource
subresource可以用来指定资源是最高优先级的。比如,在Chrome和Opera中我们可以加上下面的代码:
<link rel="subresource" href="styles.css">
和 "Link rel=prefetch"的语义不同,"Link rel=subresource"是一种新的连接关系。rel=prefetch指定了下载后续页面用到资源的低优先级,而rel=subresource则是指定当前页面资源的提前加载。
所以,如果资源是在当前页面需要,或者马上就会用到,则推荐用subresource,否则还是用prefetch。
Prerender
prerender是一个重量级的选项,它可以让浏览器提前加载指定页面的所有资源。
<link rel="prerender" href="/thenextpage.html"/>
prerender就像是在后台打开了一个隐藏的tab,会下载所有的资源、创建DOM、渲染页面、执行JS等等。如果用户进入指定的链接,隐藏的这个页面就会进入马上进入用户的视线。Google Search多年前就利用了这个特性实现了Instant Pages功能。微软最近也宣布会让Bing在IE11上用类似prerender的技术。
但是要注意,一定要在十分确定用户回点某个链接时才用这个特性,否则客户端就会无端的下载很多资源和渲染这个页面。
正如任何提前的动作一样,预判总是有一定风险出错。如果提前的动作是昂贵的(比如高CPU、耗电、占用带宽),就要谨慎使用了。虽然不容易预判用户会点进哪个页面,但还是存在一些典型的场景:
如果用户搜索到了一个明显正确的结果时,那么这个页面就很有可能被点入
如果用户在登录页面,那么登录成功后的页面就很可能接下来会被加载了
如果用户在阅读一个多页面的文章或者有页码的内容时,下一页就很可能会马上被点击了
利用Page Visibility API可以用来防止页面在还没真正展示给用户时就触发了JS的执行。
未来:Preload
<link rel="preload" href="image.png">
然而,这项草案还没有任何浏览器支持,不过值得关注。