Web Performance

How to Use preload, prefetch, and preconnect (Resource Hints)

Resource hints tell the browser what to fetch and connect to early. When to use preconnect, dns-prefetch, preload, prefetch and modulepreload, and the pitfalls.

StackOptic Research Team17 May 202610 min read
Resource hints: preload, prefetch and preconnect explained with examples

Browsers are good at loading pages, but they have a blind spot: they can only fetch a resource once they have discovered it, and discovery happens as they parse HTML and CSS — sometimes late. A font referenced deep in a stylesheet, an LCP image set by JavaScript, a connection to a font host not opened until the moment it is needed: all of these cost time the browser could have spent earlier. Resource hints are how you fix that. In short: resource hints (preconnect, dns-prefetch, preload, prefetch, modulepreload) let you tell the browser to connect or fetch ahead of time, so critical resources arrive sooner — but their power depends on restraint, because hinting everything cancels the benefit. This guide explains each hint, when to use it, and the pitfalls that turn a speed-up into a slow-down.

It is a focused companion to how to make your website load faster, where resource hints are one of the finishing touches.

Why resource hints exist

When a browser loads a page, it works through the HTML top to bottom, and only requests each resource when it encounters the reference to it. CSS and JavaScript can hide references even deeper: a font is not requested until the browser has downloaded and parsed the stylesheet that names it; an image set as a CSS background is discovered later still; a resource injected by script is discovered only when that script runs. Meanwhile, connecting to a new origin (a different domain, like a font host or CDN) is itself expensive — it needs a DNS lookup, a TCP handshake and a TLS negotiation, several round trips before a single byte of the actual resource arrives.

Resource hints let you front-run this process. They tell the browser, in effect, "you are going to need this connection or this file — start now, do not wait until you stumble across it." For a small number of critical or predictable resources, that head start can meaningfully reduce when the page becomes usable. The catch, which the whole guide returns to, is that the browser's attention and the network's bandwidth are finite, so hints are valuable precisely because they are selective.

The hints at a glance

HintWhat it doesBest forPriority
preconnectDNS + TCP + TLS to an origin, in advanceKey third-party origins you will definitely use (font host, image CDN)— (connection only)
dns-prefetchDNS resolution onlyLighter warm-up / fallback for less-certain origins— (DNS only)
preloadFetch a resource for the current page earlyThe LCP image, critical fonts, late-discovered critical CSSHigh
prefetchFetch a resource for a likely next navigationScripts/data for the page the user will probably visit nextLow (idle)
modulepreloadPreload a JS module and its dependency graphCritical ES modules in module-based appsHigh

The two on top (preconnect, dns-prefetch) prepare connections; the three below (preload, prefetch, modulepreload) fetch resources. Knowing which problem you have — a slow connection setup, or a critical file discovered too late — tells you which hint to reach for.

preconnect: warm up important origins

preconnect tells the browser to complete the full connection setup to another origin before any resource is requested from it, so the costly handshakes are already done when the real request arrives.

<link rel="preconnect" href="https://fonts.example.com" crossorigin>

Use it for origins you are certain to request from and that serve something important early — a font provider, an image or asset CDN, a video host, or an analytics/script origin that delivers a critical resource. The crossorigin attribute matters for fonts and other CORS-fetched resources; without it the warmed connection may not be reused for those requests.

The pitfall is over-preconnecting. Each preconnect opens and holds a connection, which consumes resources and competes with other work; browsers also cap how many they will honour. Warming up half a dozen origins, several of which you barely touch, wastes effort and can crowd out the connections that matter. A good rule is to preconnect to the two or three most important cross-origin endpoints and no more.

dns-prefetch: the lighter cousin

dns-prefetch does only the first and cheapest part of connection setup — resolving the domain name to an IP address:

<link rel="dns-prefetch" href="https://fonts.example.com">

Because it is so lightweight and very widely supported, it is useful in two ways: as a gentler hint for origins you are fairly but not certainly going to use, and as a companion or fallback to preconnect (some teams list both, so browsers that handle one better still benefit). DNS resolution is often a surprisingly large slice of connection time, especially on mobile, so even resolving it early can help. But preconnect, where appropriate, does strictly more — so reserve dns-prefetch for the longer tail of origins where a full preconnect would be overkill.

preload: fetch critical current-page resources early

preload is the most powerful and the most misused of the hints. It tells the browser to fetch a resource that this page definitely needs soon, at high priority, regardless of how late the browser would otherwise discover it.

<link rel="preload" href="/img/hero.avif" as="image" fetchpriority="high">
<link rel="preload" href="/fonts/body.woff2" as="font" type="font/woff2" crossorigin>

The as attribute is required and tells the browser the resource type so it can assign the right priority and apply the right policies; omitting it can cause the resource to be fetched twice. The standout use cases are:

  • The LCP image. If your largest-contentful element is an image the browser discovers late (set via CSS, or injected by script), preloading it lets the browser fetch it immediately, often moving Largest Contentful Paint substantially. Pair it with fetchpriority="high".
  • Critical fonts. Fonts are discovered only after the CSS that references them is parsed, which delays text rendering and can cause layout shift. Preloading the one or two fonts used above the fold makes them arrive sooner.
  • Late-discovered critical CSS or scripts that block rendering but are not referenced early in the HTML.

The danger is real, though: preload too much and you slow the page down. Every preloaded resource competes for bandwidth at high priority, so preloading ten things means none of them is truly prioritised — and you may pull forward resources that were not on the critical path at all, starving the ones that were. Preload the handful of resources that genuinely block first paint, and let the browser's own heuristics handle the rest.

prefetch: fetch for the next navigation

While preload is about the current page, prefetch is about the next one. It tells the browser to fetch, at low priority during idle time, a resource the user is likely to need soon:

<link rel="prefetch" href="/checkout.js" as="script">

The classic use is anticipating navigation: on a product page you might prefetch the JavaScript or data for the checkout, so when the user clicks through, much of it is already cached and the next page feels instant. Because it runs at low priority and only when the browser is idle, prefetch does not (if used sensibly) steal resources from the current page's critical work.

The judgement call is predicting correctly. Prefetching a resource the user never navigates to wastes their bandwidth — a particular concern on metered mobile connections — for no benefit. So prefetch where the next step is likely (a clear funnel, a paginated list, a wizard's next step), not speculatively across every link. Some frameworks and libraries automate this intelligently, prefetching links as they enter the viewport or on hover, which is a reasonable middle ground.

modulepreload: for JavaScript modules

modulepreload is a specialised preload for ES modules. A plain preload of a module script does not account for the module's imports, so the browser would still discover and fetch dependencies one chain at a time. modulepreload understands the module graph and can fetch the module and its dependencies ahead of time:

<link rel="modulepreload" href="/app/main.js">

This is useful in modern module-based applications where a critical entry module pulls in several dependencies that would otherwise load in a slow waterfall. As with the others, target the critical modules — typically the entry point and its most important dependencies — rather than the whole graph. And the broader lesson from how to reduce JavaScript and speed up your site still applies: preloading modules helps them arrive sooner, but shipping less JavaScript in the first place helps more.

fetchpriority: tuning the queue

Related to the hints is the fetchpriority attribute, which adjusts the priority the browser assigns to a resource it is already going to fetch:

  • fetchpriority="high" on the LCP image (or a preload of it) pushes it up the queue ahead of less important downloads.
  • fetchpriority="low" on resources that can wait — a below-the-fold image, a non-critical script — lets the important things go first.

It pairs naturally with preload: preloading the LCP image with fetchpriority="high" is one of the most reliable ways to improve LCP when the image is the bottleneck. Used together, these tools let you shape the loading order so the content that matters arrives first.

A worked example

Suppose a marketing page has an LCP of 3.6 seconds. The DevTools waterfall shows two problems: the hero image (the LCP element) is a CSS background, so it is discovered late; and the body font lives on a third-party host whose connection is not opened until the stylesheet is parsed. You make three surgical changes. First, preconnect to the font host so its DNS, TCP and TLS are done early. Second, preload the hero image with as="image" and fetchpriority="high", so the browser fetches it immediately instead of waiting to parse the CSS. Third, preload the single above-the-fold font file. You add nothing else — no extra preloads — so the three hinted resources are genuinely prioritised. The hero and font now arrive early, render-blocking on the critical path eases, and LCP drops below 2.5 seconds. This is the shape of good resource-hint work: a few targeted hints aimed at the specific resources that gate first paint, verified against the waterfall rather than guessed.

How to find what to hint (and verify it worked)

Resource hints should be driven by evidence, not added speculatively:

  1. PageSpeed Insights / Lighthouse flag opportunities directly — for example "Preconnect to required origins" and "Preload Largest Contentful Paint image" — and they name the specific origins and resources.
  2. Chrome DevTools → Network, with a waterfall view, shows what is discovered late and which connections are set up only at the last moment. Long gaps before a critical resource starts are exactly what preload and preconnect address.
  3. DevTools → Performance shows the LCP element and its load timing, helping you decide whether preloading it (and raising priority) is worthwhile.
  4. After adding a hint, re-measure: confirm the resource now starts earlier in the waterfall and that the relevant metric (usually LCP) improved. A hint that does not move the waterfall is just overhead — remove it.

The discipline of measuring before and after is what keeps a hint list short and effective rather than a pile of well-intentioned tags that quietly compete with each other.

Common pitfalls

  • Over-preloading. The cardinal sin: preloading many resources removes the prioritisation that makes preload useful, and can starve the truly critical ones. Keep the list tiny.
  • Forgetting as on preload, which can cause double-fetching or wrong prioritisation.
  • Omitting crossorigin on font (and other CORS) preloads/preconnects, so the warmed connection or fetched file is not reused.
  • Preconnecting to too many origins, wasting connections; cap it at the few that matter.
  • Speculative prefetching of pages users rarely visit, wasting their bandwidth.
  • Adding hints and never verifying, so stale or useless hints accumulate as the page evolves.

Why this is worth doing — in moderation

Resource hints are a finishing optimisation, not a foundation. They will not rescue a heavy page or a slow server — that work belongs to page weight, JavaScript reduction and server response time. But once the fundamentals are in hand, a few well-chosen hints can shave the last delays off the critical path: the LCP image fetched immediately, the font host connected early, the next page prefetched so it feels instant. The reason the whole guide stresses restraint is that hints are a zero-sum reallocation of the browser's limited attention — every resource you pull forward pushes something else back. Used surgically, on the handful of resources that demonstrably gate the experience, they are a clean win; used as a blanket, they are self-defeating. Aim for a short, evidence-led list and revisit it whenever the page changes significantly.

Go deeper

Want to see whether your site preloads its critical resources, alongside performance, SEO and security? Analyse any URL with StackOptic — free, no sign-up.

Frequently asked questions

What are resource hints?

Resource hints are small instructions you add to a page (usually as link tags in the head, or via HTTP headers) that tell the browser to do some work ahead of time — such as opening a connection to another origin or fetching a file before it is formally needed. They help because browsers normally discover resources only as they parse the HTML and CSS, which can be late; a hint lets a critical or predictable resource start earlier, reducing the delay before it is available.

What is the difference between preload and prefetch?

preload is for the current page: it tells the browser to fetch a resource you know this page needs soon, at high priority, so it is ready when required — the classic use is the LCP image or a critical font. prefetch is for a future navigation: it fetches a resource the user will probably need next (like the script for the next page) at low priority, during idle time. In short, preload speeds up this page; prefetch speeds up the next one.

When should I use preconnect?

Use preconnect for important third-party origins that you will definitely request from, such as a font provider, an image CDN or an analytics endpoint that serves a critical resource. It performs the DNS lookup, TCP handshake and TLS negotiation in advance, so when the real request comes the costly connection setup is already done. Limit it to a few key origins — each open connection has a cost, and warming up origins you barely use is wasteful.

What is the difference between preconnect and dns-prefetch?

Both prepare for a connection to another origin, but at different depths. dns-prefetch only resolves the domain's DNS, which is cheap and well supported. preconnect goes further and also completes the TCP handshake and TLS negotiation, saving more time but using more resources. A common pattern is to use preconnect for your most important origins and dns-prefetch as a lighter hint, sometimes as a fallback, for origins you are less certain about or that older browsers handle better.

Can resource hints slow down my site?

Yes, if overused. Each hint asks the browser to spend bandwidth, connections or CPU early, so preloading many resources or preconnecting to many origins makes them compete with each other and with genuinely critical work — defeating the purpose. The skill is restraint: preload only the handful of resources that block first paint (like the LCP image), preconnect only to a few essential origins, and prefetch only for navigations a user is likely to make. Used surgically they help; sprayed everywhere they hurt.

Analyse any website with StackOptic

Get the full technology stack, performance, security and SEO report in seconds — free.

Analyse a website

Related articles