Resource hints are the closest thing the browser platform has to free performance. Add a single line to your HTML head and the browser starts fetching your hero image, connecting to your CDN, or warming up DNS for your fonts before it would have otherwise. The cost is one tag. The reward is hundreds of milliseconds.
And yet most sites use them wrong, or not at all. Or worse, they preload eight things and end up slower than they started, because every preload is competing for the same early bandwidth pie.
So let me walk you through the four resource hints that actually matter in 2026, when each one helps, when each one hurts, and how to audit your current setup.
The four hints worth knowing
You'll see lots of tags described as "resource hints" in articles, but really there are four that move the needle:
- preconnect: warm up DNS, TCP, and TLS for a third party origin you'll need soon
- dns-prefetch: lighter version of preconnect, just the DNS lookup
- preload: tell the browser to fetch a specific resource right now at high priority
- fetchpriority: tweak the priority of a resource the browser already discovered
There's also prefetch (for next page resources), modulepreload (for ES modules), and the new Speculation Rules API (for prerendering whole pages). We'll cover them, but the four above are the daily drivers.
preconnect: the easiest 100 ms win
Every time the browser hits a new origin, it has to do DNS lookup, TCP handshake, and TLS negotiation. That's typically 100 to 300 ms before the first byte of any resource arrives. preconnect tells the browser "do that handshake now, I'm going to need this origin soon."
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="preconnect" href="https://cdn.example.com">
The crossorigin attribute matters when you're connecting for a font or an asset that uses CORS. Get it wrong and the browser opens a separate connection later anyway, defeating the purpose. Rule of thumb: add crossorigin for fonts. Skip it for images and most CSS.
Real impact: 100 to 300 ms of LCP improvement when your hero image lives on a different domain (CDN, image service, etc.) than your HTML.
preconnect has limits
Each preconnect costs a real connection (CPU on your server and the user's device, plus open sockets). If you preconnect to ten origins, you'll exhaust the browser's parallel connection budget and slow down everything. Limit yourself to three or four preconnect targets max. Reserve them for origins you'll definitely use in the first second.
dns-prefetch: the lighter sibling
dns-prefetch only does the DNS lookup. No TCP, no TLS. Cheaper, but smaller win. Use it for origins you'll probably need but maybe not immediately.
<link rel="dns-prefetch" href="https://www.googletagmanager.com">
<link rel="dns-prefetch" href="https://js.stripe.com">
Typical wins: 20 to 100 ms saved when the resource finally loads. Less than preconnect but lighter on the network. Good for analytics, payment SDKs, embeds.
Stack them: preconnect for critical origins, dns-prefetch as fallback for older browsers that don't support preconnect.
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="dns-prefetch" href="https://fonts.googleapis.com">
Browsers that support preconnect ignore dns-prefetch. Old browsers fall back to dns-prefetch. No conflict.
preload: the LCP weapon
preload is the big one. It tells the browser to start fetching a specific resource immediately, at high priority. The textbook use case: your hero image.
<link rel="preload"
as="image"
href="/hero.webp"
type="image/webp"
fetchpriority="high">
Without preload, the browser does not know about the hero image until it parses your HTML body and reaches the img tag. With preload, the fetch starts immediately, often saving 200 to 500 ms on LCP.
Critical attributes:
- as: tells the browser what kind of resource. Required. Wrong "as" value means the resource is fetched twice. Common values: image, font, script, style.
- type: MIME type. Useful when there are multiple format options.
- fetchpriority: high, low, or auto. Default is auto.
- crossorigin: required for fonts. Match it to the actual fetch.
What you should usually preload
- Your hero image (the LCP element)
- Your one critical web font weight
- Critical CSS if loaded async via media print swap
- Critical JS module if it's required for first interaction
What you should usually NOT preload
- Below the fold images
- Multiple font weights (one is enough)
- Third party analytics scripts
- Anything you're not sure about
Each preload steals bandwidth from other early downloads. Preload three things and you might be helping. Preload eight things and you're slowing yourself down because everything is now competing.
fetchpriority: subtle and powerful
fetchpriority is a relative new attribute (Chrome 102 plus, Safari 17 plus, Firefox 122 plus, basically universal in 2026) that lets you nudge the priority of any resource without preloading it.
<img src="hero.webp"
fetchpriority="high"
alt="..."
width="1200" height="600">
<img src="footer-logo.webp"
fetchpriority="low"
loading="lazy"
alt="...">
fetchpriority="high" on the hero image effectively does what preload does, with less ceremony. The browser bumps it to the front of the queue. We have measured 200 to 400 ms LCP improvements from this single attribute.
fetchpriority="low" on below the fold images deprioritizes them so they don't compete with the hero. Combined, you can shape resource priority across the whole page.
It also works on fetch() calls in JavaScript:
fetch('/api/critical-data', { priority: 'high' });
fetch('/api/analytics', { priority: 'low' });
Browser support is essentially universal in 2026. Use it freely.
preload vs fetchpriority: which to use when
| Situation | Best tool |
|---|---|
| Hero image discovered late in HTML | preload + fetchpriority high |
| Hero image discovered early in HTML | fetchpriority high on the img tag |
| Hero image is a CSS background | preload (browser cannot discover CSS images early) |
| Critical font | preload with crossorigin |
| Below the fold image | fetchpriority low + loading lazy |
| Third party SDK | preconnect, then defer the script |
| Next page navigation | prefetch or speculation rules |
Rule of thumb: fetchpriority is sufficient for most cases. preload is needed when the browser cannot discover the resource through normal HTML parsing.
prefetch: the next page hint
prefetch tells the browser "you don't need this for this page, but the user is likely going to a page that does, so download it during idle time."
<link rel="prefetch" href="/checkout.css">
<link rel="prefetch" href="/checkout.js">
Useful on landing pages where the next click is predictable. Product page prefetches checkout assets. Search results page prefetches details page assets. Done well, the next navigation feels instant.
Be careful. prefetching too much wastes user bandwidth, especially on mobile data plans. Prefetch only when you're highly confident about the next click.
modulepreload: ES modules specifically
If you're using native ES modules (import/export), modulepreload is the equivalent of preload but optimized for module graphs. It preloads the module and recursively preloads its dependencies.
<link rel="modulepreload" href="/app/main.js">
If you're not using native ES modules, ignore this hint. If you are, prefer modulepreload over plain preload for JS modules.
Speculation Rules API: the next big thing
Speculation Rules let you tell Chrome "prerender this whole next page in the background." When the user clicks the link, the navigation is instant because the page is already rendered.
<script type="speculationrules">
{
"prerender": [{
"where": { "href_matches": "/checkout/*" },
"eagerness": "moderate"
}]
}
</script>
Eagerness levels: conservative, moderate, eager. Conservative prerenders only when the user starts to click. Eager prerenders aggressively. Moderate is a balance.
This is huge for ecommerce, news, docs sites where navigation flow is predictable. Real measured wins: LCP on the prerendered page is essentially zero because it's already fully loaded by the time the user lands. Browser support: Chrome 121 plus, Edge, growing in others.
Use it carefully. Prerendering uses CPU and memory. If your eagerness rule matches every link, you're prerendering tons of pages the user will never visit. Match by URL pattern, not by everything.
Common resource hint mistakes
Preloading without using the resource
You add a preload for a font. You decide not to use that font. You forget to remove the preload. Now the browser is fetching a font for nothing. Lighthouse will warn you. Listen.
Wrong "as" value
preload as="script" but the resource is actually a stylesheet. The browser fetches twice. Once for the wrong type, once correctly. Worse than no preload.
Forgetting crossorigin on font preload
Font preload without crossorigin. Browser fetches the font for the preload. Then sees the @font-face rule which requires CORS. Fetches again. Free 30 KB wasted on every page load. Always include crossorigin on font preloads.
Preloading too many things
I've seen sites preload 12 resources on the homepage. Every preload competes for the early bandwidth window. The result: nothing arrives sooner, and several things arrive later. Limit yourself to one to three preloads per page. Quality over quantity.
Using preload for next page assets
preload says "I need this for this page." prefetch says "I'll need this later." Mixing them up means current page priority is wasted on something the user won't see for 30 seconds.
Preloading the same thing twice
Once via <link rel="preload"> and once via fetchpriority="high" on the actual element. Browsers handle this OK now but on older versions you got duplicate fetches. Pick one or the other for any given resource.
How to audit your current resource hints
Open Chrome DevTools, go to Network tab, reload the page. Look at the priority column. Your hero image should be priority high. Critical CSS should be priority highest. Below the fold images should be priority low. If priorities don't match what you'd expect, your hint setup is off.
Also check the Lighthouse audit "Preload key requests." If Lighthouse suggests preloading something, it usually has a real LCP win attached. Read the recommendations.
And use our free analyzer if you want a one click audit. We flag missing preloads, missing fetchpriority hints, and unused preloads in one report.
The complete resource hints recipe
For a marketing landing page in 2026, this is the head section that should be your default starting point:
<!-- DNS and connection warmup for third parties -->
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="preconnect" href="https://cdn.example.com">
<!-- Critical font -->
<link rel="preload"
as="font"
type="font/woff2"
href="/fonts/inter-700.woff2"
crossorigin>
<!-- Hero image -->
<link rel="preload"
as="image"
type="image/webp"
href="/hero.webp"
fetchpriority="high">
<!-- Critical CSS via inline + deferred full -->
<style>/* critical inlined here */</style>
<link rel="preload" href="/full.css" as="style">
<link rel="stylesheet" href="/full.css" media="print" onload="this.media='all'">
<!-- For predictable next navigation -->
<script type="speculationrules">
{ "prerender": [{ "where": { "href_matches": "/pricing" }, "eagerness": "moderate" }] }
</script>
Tweak per page. The hero preload changes per template. The font preload usually stays the same. The preconnects depend on which third parties you load.
How resource hints connect to the rest of CWV
Resource hints touch LCP and FCP hardest. They don't directly help CLS or INP, but a well preloaded font (with size-adjusted fallback) does cut CLS swap shift. Combined with our other recommendations:
- Fix LCP: hero image preload + fetchpriority is the highest impact pair
- Font loading: preload one weight, with crossorigin, every time
- Critical CSS: pair the inline block with a preload for the full CSS
- Third party scripts: preconnect to their origin, defer the actual script
Resource hints alone won't fix a slow site. But on a site that's already mostly tuned, they're the cheapest 200 to 500 ms you'll ever ship.
Resource hints for SPAs and the deeper Speculation Rules dive
Single page apps add a wrinkle to resource hints. The first cold load is one navigation. Every click after that is a JavaScript swap. So traditional preload hints in the HTML head only help that first load.
For SPA navigation, you have two tools: prefetch and Speculation Rules. Prefetch is older, more compatible, less powerful. Speculation Rules is newer, more powerful, mostly Chromium for now but spreading.
Prefetching SPA chunks
Most SPA bundlers (Webpack, Vite, Rollup) split your code into chunks. The home page chunk loads on the home page. The pricing chunk only loads when the user navigates to pricing. The naive approach waits for the click, then fetches the chunk, then renders. Adds 100 to 400 ms of feel-bad latency.
The fix: prefetch the next likely chunk after the page is idle.
// React Router has built in support
<Link to="/pricing" prefetch="intent" />
// Manual approach
const link = document.createElement('link');
link.rel = 'prefetch';
link.href = '/static/js/pricing.chunk.js';
link.as = 'script';
document.head.appendChild(link);
Frameworks like Next.js do this automatically with the Link component. Good defaults are good defaults.
Speculation Rules in production: where it really shines
Documentation sites, ecommerce, news. Anywhere navigation paths are predictable, prerender the next page entirely.
<script type="speculationrules">
{
"prerender": [
{
"where": { "and": [
{ "href_matches": "/products/*" },
{ "not": { "href_matches": "/products/*/checkout" } }
]},
"eagerness": "moderate"
}
],
"prefetch": [
{
"where": { "href_matches": "/blog/*" },
"eagerness": "conservative"
}
]
}
</script>
That config prerenders any product page the user is likely to click, prefetches blog posts, but excludes the checkout flow because prerendering checkout has weird side effects with analytics and payment SDKs.
Eagerness levels matter. Conservative only fires on actual click. Moderate fires on hover or touchstart. Eager fires as soon as the link is visible. More eager equals faster perceived navigation but more wasted bandwidth and CPU. Match the level to user behavior. For a small site where every visitor reads three blog posts, eager is fine. For a sprawling docs site where users only read one section, conservative.
Measuring resource hint impact
The temptation is to add hints and assume they help. Always verify. Lighthouse has a "Use video formats" and "Preload key requests" audit which fires on real measured opportunities. Compare LCP before and after via CrUX field data over a couple of weeks. If the hint did not move the field number, it was not actually on the critical path.
The hint that almost nobody uses but should
fetchpriority="low" on below the fold images. The browser default is "auto" which often means medium priority. Marking below the fold images as low frees up bandwidth for your hero. Five minute change, sometimes 100 ms LCP improvement on image heavy pages.
<img src="hero.webp" fetchpriority="high" alt="">
<img src="footer-illustration.webp" fetchpriority="low" loading="lazy" alt="">
Combine with loading="lazy" for true below the fold. Not lazy plus low priority for stuff just below the fold that the user scrolls to within a couple seconds. The two attributes work together.
Frequently asked questions
How many preloads is too many?
More than three on a single page. Every preload competes for early bandwidth. Two is the sweet spot for most sites: one hero image, one critical font.
Does preconnect work for same origin resources?
It's redundant. The browser is already connected to your origin. preconnect is for third party origins your page also uses.
Should I preload below the fold images?
No. Use loading="lazy" instead. Preload is for the LCP element and other above the fold critical resources only.
Can I use fetchpriority on script tags?
Yes. fetchpriority="low" on async non critical scripts and fetchpriority="high" on critical scripts works in all modern browsers.
What's the difference between prefetch and prerender?
prefetch downloads resources for the next page. prerender (via Speculation Rules) actually renders the next page in the background, including running scripts and CSS. prerender is more powerful but more expensive.
Will resource hints hurt mobile users on slow connections?
Bad ones can. preloading 8 things on a 3G phone with limited bandwidth makes things worse. Sensible ones (one hero, one font) help even on slow connections because they reorder priority, not just fetch more.
Are resource hints a Core Web Vitals ranking signal?
Indirectly. They are not a ranking signal themselves. But they impact LCP and FCP, which are signals. Better hints equals better LCP equals better ranking on competitive queries.
See Which Hints You're Missing
Our free analyzer flags missing preloads, missing preconnects, missing fetchpriority. Run your URL and get a punch list of exactly what to add.
Run a Free Audit →Want this dialed in by humans?
We audit, add the right hints, remove the wrong ones, and verify the LCP and FCP improvement on your real site. 48 hour turnaround. Money back if scores don't improve.
View Expert Fix Service →