Woow: DNS Prefetch, Preconnect, Preload, HTTP/2 Server Push, Prefetch and Prerender.
All those technologies can all be collectively called Resource Hints and the last two; prefetch & prerender, can also recognized as prebrowsing; coined from term predictive browsing.
Resource hints can be divided into exactly 6 types. Note that the only one not implemented is HTTP/2 Server Push as it is as of time of writing, still unsupported by major web servers, apache and nginx.
To recap, techniques are:
- DNS Prefetching / current page (
- Domain Preconnect / current page (
- Resource Preload / current page (
subresourcethat is depreciated)
- HTTP/2 Server Push / current page
- Link prefetching / next page (
- Prerendering / next page
As most of there technologies should be somehow aware of the real site content and/or user behavior, the best way to trigger them is from Wordpress, not from server side.
There are couple of optimizations that can be achieved most easily directly from server, notably from Google Pagespeed module, and you should use these immediately.
I expect a lot of plugins for these purpose in the future, but for now, there are already couple of good ones in existence.
DNS resolution speed can be improved with DNS Prefetching, a technique adopted by most modern browsers.
There a couple of domains obvious to prefetch DNS and those include both your specific domain CDN and any public CDN’s you probably use (Google for example).
<link rel="dns-prefetch" href="//fonts.googleapis.com"> <!-- Google Fonts --> <link rel="dns-prefetch" href="//www.google-analytics.com"> <!-- Google Analytics --> <link rel="dns-prefetch" href="//www.googletagmanager.com"> <!-- Google Tag Manager -->
I read somewhere that it is not recommended to use more than 5 URLs for DNS prefetching, but that’s simply not true.
Good candidates for DNS prefetching are:
- Resources on different domains hidden behind 301 redirects
- Resources for analytics which usually come from different domains, but this will browser figure out alone, without help.
Pagespeed filter insert_dns_prefetch
<link rel="dns-prefetch"> tags in page head and it does it
automaticly for all domains present in the document.
Good article on this theme.
Preconnect is used to indicate origins for resources on current page. We use preconnect to pre-open a new TCP connection.
It is perfect when you are not sure of a full resource URL, but you surely know the origin domain from which the resources are going to be fetched.
We can call it extended DNS prefetch, as it very similar but so much powerful as it initiates a complete early connection, which includes the DNS lookup, TCP handshake, and optional TLS negotiation.
<link href='https://fonts.gstatic.com' rel='preconnect' crossorigin> <link href='https://fonts.googleapis.com/css?family=Roboto+Slab:700|Open+Sans' rel='stylesheet'>
The reference material is on link type
preload and on HTTP/2 Server
Push is this document: Preload.
Unlike DNS prefetching, resource prefetching is a more expensive operation; be mindful of how and when to use it.
<link rel='preload' href='critical.js'> <link rel='preload' href='main.css'>
Preload is a mandatory and high-priority fetch for a resource that is necessary for the current navigation.
Note: Preloading was in the past known as Subresource prefetching.
rel=subresource is deprecated as of january 2016 and is
superseded with the new,
HTTP/2 Server Push
Server push is similar to Preloading, but it eliminates the request
roundtrip between client and server for the declared
Not sure how it’s working, but I expect we just have to enable server support for this option to work out of the box?
Prefetch is an optional browser mechanism, lowest priority fetch for a resource that might be used by a subsequent navigation. In another words, it usualy utilizes browser idle time to download resources that the user might visit in the near future.
Also known as link prefetching and is already adopted by most major browsers.
<link rel='prefetch' href='secondary.js'>
Prefetching does work across domains, including pulling cookies from those sites.
It is similar to prefetch but now the whole document with all its resources is fetched and rendered in background.
So we must very carefully to try to predict users actions and optimistically load resources ahead of time for better performance.
Luckily, we can trigger prerendering by inserting a link element with a
rel='prerender', for example:
<link rel='prerender' href='http://www.mypage.com'>
Luckily, we can inject prerendering hints at runtime, based on user action, which is probably the most realistic usage scenario.
var hint =document.createElement("link") hint.setAttribute("rel","prerender") hint.setAttribute("href","next-page.html") document.getElementsByTagName("head").appendChild(hint)
For example, if a user hovers over an element long enough, we can start prerendering. Great usage of similar idea is a JS plugin that prerenders pages on link hovers - smoothState.js. It already has proper Wordpress integrations implemented here
Prerendering is the most costly of all techniques and misusing it can cause major bandwidth waste, especially on mobile devices.
We can test the prerendering with this simple tool.
Notes on prerendering
If you try to test for prerendering, please note that Chrome doesn’t use it when Developer Tools is open. You can see if a page is being prerendered at
Google Analytics supports this and it won’t count visits or any other stat coming from a prerendered page.
<link rel="dns-prefetch" href="//cdn.save-up.at"> <link rel="preconnect" href="//cdn.save-up.at" crossorigin>
Prefetch is for next navigation, but subresource prefetch is for current:
<link rel="prefetch" href="/library.js" as="script">
The prerender link relation type is used to identify a resource that might be required by the next navigation:
<link rel="prerender" href="//example.com/next-page.html">
In addition to specifying the hint type, the application may indicate the expected probability that the specified resource hint will be used.
<link rel="dns-prefetch" href="//widget.com" pr="0.75"> <link rel="preconnect" href="//cdn.example.com" pr="0.42"> <link rel="prefetch" href="//example.com/next-page.html" pr="0.75"> <link rel="prerender" href="//example.com/thankyou.html" pr="0.25">
Details on prerendering
The following reference document on Chrome Prerendering gives us explanation and an answer to very important questions.
Does a prerender follow 301 redirect? Yes, by default; but you can stop that on request.
If the server sends a redirect response for a subresource with a “Follow-Only-When-Prerender-Shown: 1” header, Chrome will hold off on following the redirect and on fetching the respective subresource until the prerender is shown to the user.
Are cookies set? They are set only if prerendered page is displayed.
Cookies made by the prerendered page are not visible to other tabs until the user has activated the page. If the user never uses a prerendered page, cookies will just disappear.
We can check the current prerender status on chrome://net-internals/#prerender page.
As for Firefox, they use term prefetch, not prerender. Important document from 2010 on HTML5 Link Prefetching explains couple of important notes:
- Prefetching does work across domains, including pulling cookies from those sites.
- Prefetching can throw off website statistics as the user doesn’t technically visit a given page.
What’s in it for us?
DNS-prefetch our CDN, affiliate networks and public CDN’s
I did notice that Pagespeed is not adding a CDN subdomain here, and it should do it.
Preconnect to our CDN, for sure.
Prefetch domain of our affiliate link on a page On shop pages, do it like this:
Based on the fact that prefetching does work across domains, including pulling cookies from those sites.
/coupon/123is a 301 redirect and it is
noindex. On Shop page we link to
nofollow. It is safe to prerender
/coupon/123and it will work. Index will not go there but browser will follow redirects and prerender valid page. Cookies would not be set, until user really visits that page.
Please note that, if we have page-per-view links or tracking pixels, those statistics will be really off because of this.
You can always prerender home page as it will probably at some point go there.
Prerender some our page that will be next shop page: no idea what will be this? magazin page: home, menu items and/or then first shop that is displayed. We can prefetch & prerender all the pages from main menu links.
For now, only
preconnect are sure. The first one is
easily done with pagespeed.
There is an perfect JS library schliflo/BoostR to help about dynamically using preconnect, preload and prerender.
Total explanation! Very important comment: Comments on the A List Apart Article One Step Ahead: Improving Performance with Prebrowsing
Prefetch is meant to be used for resources required by the next navigation, which means that they will be downloaded with low priority or not at all, and always after all other resources have finished loading. As a result, prefetch should not be used for hinting critical resources on the current page.
This is also the reason why Chrome introduced
current page, but subresource has its own set of problems. so I wouldn’t
recommend that either.
In short: use dns-prefetch for current and next pages; use prefetch and prerender to fetch resources for next navigation.
Some Wordpress support?