Pre技术:预加载技术。提供在不影响当前页面情况下,浏览器预加载资源的性能优化方案。
比较出名的Pre是dns-prefetch
,用于告知浏览器预先获取指定的域名的DNS,以便在使用时可以减少DNS查找。除了dns-prefetch外,还有几个“不出名”的Prer技术,本文将对现有的几个Pre技术做一个简单的介绍,这些技术都是使用link
标签定义。
DNS Prefetch
就是上述提到的,用于告知浏览器,尽可能预先解析指定域名的DNS。使用方式:
<link rel="dns-prefetch" href="//the-domain-to-be-prefetched.com" />
至于兼容性,可以说是目前为止所有的Pre技术里最好的了,具体可以查看http://caniuse.com/#search=dns-prefetch
IE是从IE9开始支持DNS Prefetch的,但是,是从IE10开始支持dns-prefetch
。IE9里,并不是使用dns-prefetch
来定义一个DNS的预解析,而是使用prefetch
。挺尴尬的,因为prefetch在w3规范里又被用到了另一个Pre技术,下面会讲到。。
Preconnect
预连接。和DNS Prefetch类似,但是,更进一步。它不仅要求浏览器预解析指定域名的DNS,还需要预先与服务器握手以及TLS协商(如果使用了HTTPS)。使用方式:
<link rel="preconnect" href="//the-domain-to-be-preconnect.com" crossorigin="anonymous" />
兼容性查看http://caniuse.com/#search=preconnect
由于会与服务器握手,因此,就需要确定“是否跨域”。和script类似,带crossorigin
属性,以告知浏览器如何处理跨域和cookie。
Prefetch
上述DNS Prefetch里提到过,IE9里使用的DNS Prefetch类型名是prefetch,但是,这个类型名在规范里又被用于另外一个意图。
Prefetch:预获取,在Preconnect基础上更进一步,它要求浏览器获取整个的指定资源,link[href]
值指定的是某个具体资源,而不是简单的一个域名了。除了和Preconnect一样拥有rel
、href
和crossorigin
外,还有as
,可用于告知浏览器资源类型,这个类型和MIME不一样,是一个统称类型,比如:所有的图片都是as="image"
,JS的是as="script"
,HTML的是 as="html"
等,具体可以参考https://fetch.spec.whatwg.org/#concept-request-destination。使用方式:
<link rel="prefetch" href="//the-domain.com/prefetch.js" crossorigin as="script" />
as属性并不是必须的,但是建议加上,以便浏览器能更好的添加请求Header来优化资源的获取。
使用Prefetch,整个资源都会被加载,但是,浏览器不允许对资源预处理或执行,资源只是被提前加载,并缓存起来,以便将来使用
。
兼容性查看http://caniuse.com/#search=prefetch
Prerender
预渲染。与Prefetch类似,浏览器会下载整个资源,但是,Prefetch不允许浏览器对资源做预处理和执行,而Prerender则会告知浏览器,下载资源(HTML)并解析/执行它,包括被解析资源的子资源,这意味着会下载该HTML中的图片、样式、脚本等等。
Prerender没有as属性,它下载的是HTML,使用方式
<link rel="preconnect" href="//the-domain-to-be-preconnect.com" />
由于不允许对当前页面产生影响,浏览器设置预渲染的页面visibilityState属性为hidden。
兼容性查看http://caniuse.com/#search=prerender
建议少用这个,太耗资源。而且,查看上述兼容性,你会看到Chrome 58里又把这个功能干掉了。。。。。。
Preload
预加载。这是一个和Prefetch几乎一模一样的功能,但是,其加载的资源适用的场景又完全不一样。使用方式只是将上述Prefetch中的prefetch改成preload。其他的完全一样:
<link rel="preload" href="//the-domain.com/prefetch.png" crossorigin as="image" />
与Prefetch*不同之处在于:
- Prefetch的优先级很低,低到浏览器
可以不加载
- Preload的优先级很高,浏览器
一定要加载
- Prefetch加载的资源用于
将来某个页面
中(这意味着它可能压根不会被用到)- Preload加载的资源用于
当前页面
中
所以,在使用prefetch还是preload时候,需要考虑上述的不同点,而不应该盲目使用。[Preload以前叫Subresource]
兼容性查看http://caniuse.com/#search=preload
最后,上述Pre技术,除了Preload,其他的Pre都可能“不被浏览器执行”,这不是兼容性的问题,而是,这些Pre都不是浏览器必须行为,浏览器会根据一定的策略决定是否Pre相应的资源或操作,这些策略包括:CPU、内存等的占用率。
有空的话,我再另外写个文章,介绍一下具体使用Prefetch和Preload的优化效果吧。
P.S. 参考
- https://w3c.github.io/resource-hints/
- IE10 now supports LINK REL=dns-prefetch. In IE9, we only would perform DNS prefetch for LINK REL=prefetch as the dns-prefetch token was not yet defined. (see https://blogs.msdn.microsoft.com/ieinternals/2012/03/01/internet-explorer-10-consumer-preview-minor-changes-list/)