You've probably seen dns-prefetch
and preconnect
mentioned in performance discussions and wondered what they actually do. I used to just skip over them until I finally took the time to understand how they work.
Turns out, they're actually pretty useful once you get what they're for.
The Basic Idea
Think of loading resources from other websites like making a phone call. Your browser has to:
- Look up the phone number (DNS lookup)
- Dial and wait for connection (TCP)
- Do the security handshake (SSL for HTTPS)
- Finally ask for what it needs
Resource hints let you start this process early, before you actually need the resource.
DNS-Prefetch: Just the Phone Number
<link rel="dns-prefetch" href="//example.com">
This tells your browser "hey, look up example.com's IP address now, we'll need it later." That's it - just the DNS lookup part. No connection, no handshake.
Usually saves 50-200ms, but can be much more on slow connections.
Preconnect: The Full Setup
<link rel="preconnect" href="https://example.com">
This does everything - DNS lookup, opens the connection, does the SSL handshake. When you actually need the resource, everything's ready to go.
More forceful, but also more effective when you know you'll definitely need something.
The Real Performance Impact
I tested this on various sites and here's what actually happens:
dns-prefetch saves you:
- 20-120ms on good connections
- 200-400ms on mobile/slow connections
- Uses almost no resources
preconnect saves you:
- 200-600ms total connection time
- Sometimes over a second on slow mobile
- But uses up connection slots
The difference is huge on mobile. I tested on throttled 3G and dns-prefetch alone cut 300ms off some page loads.
Browser Differences
Most modern browsers handle these well, but they all have their quirks:
- Chrome is pushy with preconnect - keeps connections open longer
- Safari is picky and sometimes ignores hints it thinks are unnecessary
- Firefox sits in the middle
- Mobile browsers are more careful about battery life
Older browsers just ignore these hints completely, which is fine - your site still works.
When to Use Each One
After way too much experimentation, here's what actually works:
Use dns-prefetch for "maybe" stuff:
- Analytics that might not load right away
- Social media widgets
- Ad networks
- Any third-party script that's not critical
<!-- Stuff that might load later -->
<link rel="dns-prefetch" href="//www.google-analytics.com">
<link rel="dns-prefetch" href="//fonts.googleapis.com">
<link rel="dns-prefetch" href="//connect.facebook.net">
<link rel="dns-prefetch" href="//platform.twitter.com">
<link rel="dns-prefetch" href="//pagead2.googlesyndication.com">
Use preconnect for "definitely" stuff:
- API endpoints you'll hit immediately
- CDNs serving critical resources
- Font files that load right away
- Images above the fold
<!-- Critical stuff that loads immediately -->
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="preconnect" href="https://api.mysite.com">
<link rel="preconnect" href="https://cdn.mysite.com">
For more detailed HTML optimization techniques, check out Web Utility Labs' HTML guide which covers these concepts in depth.
Real Examples
Online Store
<!-- E-commerce site example -->
<!-- Product images are above fold, need them fast -->
<link rel="preconnect" href="https://cdn.shopify.com">
<link rel="preconnect" href="https://images.shopify.com">
<!-- Tracking stuff can wait -->
<link rel="dns-prefetch" href="//www.google-analytics.com">
<link rel="dns-prefetch" href="//facebook.com">
<link rel="dns-prefetch" href="//googletagmanager.com">
<link rel="dns-prefetch" href="//hotjar.com">
Blog Site
<!-- Blog/content site -->
<!-- Typography matters, fonts load first -->
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="dns-prefetch" href="//fonts.googleapis.com">
<!-- Revenue stuff but not critical path -->
<link rel="dns-prefetch" href="//googleads.g.doubleclick.net">
<link rel="dns-prefetch" href="//disqus.com">
<link rel="dns-prefetch" href="//carbonads.net">
Dashboard App
<!-- SaaS dashboard -->
<!-- API calls happen on page load -->
<link rel="preconnect" href="https://api.dashboard.com">
<link rel="preconnect" href="https://cdn.dashboard.com">
<!-- Support and analytics are secondary -->
<link rel="dns-prefetch" href="//widget.intercom.io">
<link rel="dns-prefetch" href="//www.google-analytics.com">
<link rel="dns-prefetch" href="//js.stripe.com">
Common Mistakes to Avoid (The Hard-Won Lessons)
Okay, so here's where I'm gonna be brutally honest about the dumb stuff I've done while learning this...
Connection limits are real. And I mean REAL. I once spent an entire afternoon wondering why my perfectly crafted preconnect hints weren't working, only to discover I'd added like 12 of them. Browsers just laugh at you after the first 4-6. It's like trying to hold too many conversations at once - eventually you just start ignoring people.
Mobile browsers are sneaky little things. What works beautifully on your laptop will sometimes completely fall apart on an actual phone with a spotty connection. I learned this the hard way when a client called me panicking because their site was slower on mobile after my "improvements." Turns out mobile browsers are way more careful about keeping connections open because, you know, battery life actually matters to people.
Be explicit about HTTPS. Don't use //example.com
- use https://
or http://
. I used to think I was being clever with protocol-relative URLs, but you just end up with wasted connections and confusion. Pick one and stick with it.
Fonts need crossorigin. This one drove me absolutely nuts for weeks. Google Fonts and most font CDNs require the crossorigin attribute or you'll get duplicate connections. I kept seeing two connections to the same font server and couldn't figure out why:
<!-- Wrong: This won't work like you think -->
<link rel="preconnect" href="https://fonts.gstatic.com">
<!-- Right: Fonts need crossorigin or you get double connections -->
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
Connections time out. Preconnect connections don't stay open forever - usually 10-30 seconds. I once preconnected to an API that only got called when users clicked a specific button, which most people never did. Completely wasted hint.
How to Actually Test This Stuff
Open Chrome DevTools, go to Network tab, disable cache, and reload your page. I know, I know, everyone says this, but actually DO it.
Look for those colored bars in the timing section:
- Purple = DNS lookup
- Orange = Initial connection
- Green = SSL handshake
With good resource hints, these should happen early while your HTML loads, not right before each resource loads. It's like seeing the prep work happen in the background while the main show is starting.
WebPageTest is better for detailed analysis, especially for mobile performance. But honestly? Start with DevTools. It's right there, it's free, and it'll show you 90% of what you need to know.
Getting Creative with JavaScript (Because Why Not?)
Once you understand the basics, you can get fancy. I built this little thing that adds preconnect hints when people hover over external links:
// Preconnect on hover for external links
const links = document.querySelectorAll('a[href*="external-site.com"]');
links.forEach(link => {
link.addEventListener('mouseenter', function() {
// Check if hint already exists
if (document.querySelector('link[href*="external-site.com"]')) return;
// Create and inject preconnect hint
const hint = document.createElement('link');
hint.rel = 'preconnect';
hint.href = 'https://external-site.com';
document.head.appendChild(hint);
}, { once: true });
});
This adds preconnect hints when users show interest. Pretty neat for external links or optional resources. Though I'll be honest - this is probably overkill for most sites.
Real Results (Numbers Don't Lie)
I tested these hints on a client's blog for a month. About 15k visitors, mix of desktop and mobile traffic. Real users, real connections, real frustrations when things were slow.
- Before any hints: 3.4 second average load time
- Added dns-prefetch: 3.1 seconds (300ms better)
- Switched some to preconnect: 2.6 seconds (800ms better)
- Went overboard with preconnects: 3.0 seconds (worse!)
The sweet spot was 2 preconnects for critical stuff, 4-5 dns-prefetch for everything else. Your mileage will vary, but that's a decent starting point.
Mobile is Where This Really Matters
Mobile connections are where this stuff really shines. DNS lookups that take 30ms on your office WiFi can take 400ms on spotty LTE. I've seen it take over a second on really bad connections.
But mobile browsers are also protective of battery life. They'll close unused connections quickly and limit how many preconnects actually work. It's like they're saying "we'll help you, but we're not gonna kill the battery doing it."
My mobile strategy: use dns-prefetch liberally, preconnect very selectively. Maybe 1-2 preconnects max for mobile users. And always, ALWAYS test on actual devices with throttled connections.
My Biggest Screw-Ups (Learn from My Pain)
Using preconnect for everything. Seems logical - if some is good, more is better, right? Wrong. So very wrong. Browsers have limits and they will ignore you.
Forgetting about mobile. Desktop performance isn't mobile performance. Period. End of story. Test on actual devices with slow connections or you're just guessing.
Not matching protocols. If your site is HTTPS, make sure your hints are too. Mixed protocols are just confusing for everyone involved.
Ignoring crossorigin. Fonts, some CDN resources, API calls - lots of stuff needs that crossorigin attribute. Don't ask me why, just add it.
Tools That Actually Help
- WebPageTest - Best for detailed connection analysis, but can be overwhelming
- Chrome DevTools - Quick testing, Network tab shows timing bars
- Lighthouse - Will suggest missing resource hints for third-party stuff
- GTmetrix - Good overview reports, less intimidating than WebPageTest
I usually start with DevTools for quick checks, then use WebPageTest when I need to really understand what's happening.
Just Start Simple
Don't overthink this. Seriously. I spent way too much time trying to perfect my resource hints before I even had the basics working.
Start by adding dns-prefetch for all your external domains - analytics, fonts, CDNs, whatever. Takes five minutes and helps immediately. Then look at what loads first on your page. If it's from an external domain and users definitely need it, upgrade that to preconnect.
Test on mobile. Test on slow connections. Your fancy office internet doesn't represent real users.
The Reality Check
These hints aren't some miracle cure. They're one small piece of making websites faster. They work best combined with proper caching, optimized images, and not loading 47 different tracking scripts (we've all been there).
Your users don't care about your technical metrics. They care about whether your site feels fast. Sometimes that means 500ms of technical improvement, sometimes it means showing a loading spinner so people know something's happening.
Focus on the big wins first - optimize images, enable compression, fix slow database queries. Then come back to resource hints for that extra polish.
But when you do use them, use them right. Your users will thank you, even if they never know why your site feels snappier than the competition.
This stuff took me way too long to figure out properly. The docs make it sound simple but real-world usage has all these weird issues and browser problems. Start small, test everything, and remember that faster is always better than perfect.
Ready to Optimize Your HTML?
Want to dive deeper into HTML optimization and performance? Check out my comprehensive HTML guide at Web Utility Labs for more practical tips and tools to make your websites lightning fast.
Top comments (0)