Flite Careers

Improving Page Performance With HTML5 DNS Prefetch

DNS hostname resolution, or the time it takes to translate a domain name to an IP address, is a big bottleneck in web application performance. Each request that results in a DNS lookup means users wait longer for the page to load. We’ve known for years that even small delays can result in decreased user interaction rates and lost revenue.

Fortunately, there’s a relatively new HTML5 feature that helps prevent DNS resolution delay called DNS prefetching. At Flite, we recently implemented DNS prefetching in our JavaScript code that injects rich media ads. With this minor change, we observed an immediate performance improvement in browsers that support prefetching.

Limitations with Dynamic Content

Web browsers, especially Chrome, have gotten much smarter about when to perform DNS lookups. In particular, the current behavior for Chrome is to start prefetching host names found in the href attribute of anchor tags on the page (type about:dns in the omnibox to see this in action).

Chrome and other browsers may have gotten much smarter about anticipating DNS lookups, but unfortunately this approach doesn’t work for script-injected content on the page, including Flite’s rich media ads or Twitter’s tweet timeline widget. Browsers aren’t able to determine what external resources a <script> tag is going to load. This is also a problem with links that redirect to a different domain.

Solution: Manual DNS Prefetching using <link rel=’dns-prefetch’>

In modern browsers, there’s a straightforward way to tell the browser to perform a DNS prefetch for a particular hostname. It’s just a matter of inserting a special type of link tag:

1
<link rel="dns-prefetch" href="//some-hostname.com">

This isn’t guaranteed to work in all cases, however. Chrome doesn’t prefetch DNS requests on HTTPS requests for security reasons, so the prefetch tag would be ignored on a secure page. Also, special HTTP headers or <meta> tags can disable DNS prefetching entirely.

Performance Benefits: Case Study Using Prefetch with the Twitter Timeline Widget

Using the indispensable WebpageTest.org, we’re able to easily compare the the difference between loading script-injected content with and without DNS prefetching.

For example, compare the connection diagrams for loading Twitter’s timeline widget with and without<link rel=’dns-prefetch’> tags. Pay close attention the the narrow green bars at the start of each connection – that color represents DNS lookup time:

Figure A: Without DNS Prefetch

1
2
<a class="twitter-timeline" href="https://twitter.com/flite" data-widget-id="redacted">Tweets by @flite</a>
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

Figure B: With DNS Prefetch

1
2
3
4
5
6
7
8
9
10
<!-- Tell the browser what domains the twitter widget is going to access -->
<link rel="dns-prefetch" href="http://platform.twitter.com" />
<link rel="dns-prefetch" href="http://cdn.syndication.twimg.com" />
<link rel="dns-prefetch" href="http://r.twimg.com" />
<link rel="dns-prefetch" href="http://p.twitter.com" />
<link rel="dns-prefetch" href="http://cdn.api.twitter.com" />

<!-- Twitter Widget Code -->
<a class="twitter-timeline" href="https://twitter.com/flite" data-widget-id="redacted">Tweets by @flite</a>
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

As you can see in Figure B, the DNS requests happen seconds earlier with the DNS prefetch tags. The five link tags that we put on the page before the widgets.js script tag causes to browser to prefetch the DNS lookups to those domains. Later, when widgets.js makes requests to resources on those domains, Chrome already has the IP addresses in the cache.

Conclusions

DNS prefetch is a safe, backward-compatible HTML5 feature that can help with perceived performance. This is particularly true on pages that load dynamic content from several domains. While not supported in Internet Explorer until version 10, DNS prefetch is available in recent Webkit and Firefox versions.

Modern web pages now have an average of over 80 subrequests, and DNS prefetching should certainly be considered for decreasing latency of script-initiated subrequests when performance is critical.