Problem Solved

HTML · preload & preconnect

Home › Courses › HTML › Problems › Preload & preconnect
📄 Concept · 3 min read

Preload and preconnect.
Fetch before the browser knows.

Resource hints tell the browser about resources before it discovers them in the HTML. preload says "we need this now, fetch it first." preconnect says "we'll need this domain, open a connection." prefetch says "we'll need this later, fetch in idle time." Each one saves real time — but used incorrectly, they hurt more than help. This page covers when each one is appropriate.

Short answer: Use rel="preconnect" for the 2–3 third-party domains you'll definitely fetch from (fonts, CDN, API). Use rel="preload" for the 1–2 critical resources needed for first paint — usually the main font and the hero image. Use rel="dns-prefetch" as a fallback for older browsers. Use rel="prefetch" for the next page in a user flow. Too many hints compete for bandwidth and slow down everything.

✅ The four resource hints

Each one solves a different problem.

rel="preload"

Fetch a resource the current page needs. High priority. For critical fonts, CSS, images above the fold. Use 1–3 max.

rel="preconnect"

Open a connection to a domain (DNS + TCP + TLS). For third-party APIs, fonts, CDNs. Use 2–3 max.

rel="dns-prefetch"

DNS lookup only. Cheaper than preconnect. Fallback for older browsers, or extra domains beyond the preconnect limit.

rel="prefetch"

Fetch a resource for a future page. Idle-time download. For the next step in a flow — cart → checkout.

✅ Before and after

The same page, without and with resource hints.

without-hints.html
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="/style.css">
</head>
<body>
<h1 style="font-family: 'Inter', sans-serif;">Hello</h1>
<img src="/hero.jpg" alt="Hero" width="1200" height="600">
<script src="https://cdn.example.com/analytics.js"></script>
</body>
❌ Browser discovers the font only after parsing
style.css → +200ms before font fetch starts.
❌ Hero image found during HTML parse → +50ms
delay before download starts.
❌ CDN domain not connected until script needs it
→ +150ms DNS + TCP + TLS handshake.

Total blocking delay: ~400ms before real
content can paint.
with-hints.html
<head>
<meta charset="UTF-8">

<!-- Preconnect to third-party domains -->
<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">

<!-- Preload the hero image -->
<link rel="preload" as="image" href="/hero.jpg">

<!-- Preload the font file -->
<link rel="preload" as="font"
href="/fonts/inter-var.woff2"
type="font/woff2" crossorigin>

<link rel="stylesheet" href="/style.css">
</head>
<body>
<h1 style="font-family: 'Inter', sans-serif;">Hello</h1>
<img src="/hero.jpg" alt="Hero" width="1200" height="600">
<script src="https://cdn.example.com/analytics.js"></script>
</body>
✅ Font domain connected immediately (+0ms).
Font file downloading in parallel with CSS.
✅ Hero image downloading immediately.
✅ CDN connected before script needs it.

Total blocking delay: ~50ms — 350ms faster.

✅ Preconnect saves 100-300ms per domain.
✅ Preload saves 100-500ms per resource.

Rule: preload what blocks first paint.
preconnect what the page will fetch from.
Never preload what you don't need immediately.

✅ Font preload — the crossorigin gotcha

Fonts need crossorigin, always.

font-preload.html
<!-- ✅ Correct font preload -->
<link rel="preload"
href="/fonts/inter-var.woff2"
as="font"
type="font/woff2"
crossorigin>

<!-- ❌ Missing crossorigin — font downloaded twice -->
<link rel="preload"
href="/fonts/inter-var.woff2"
as="font"
type="font/woff2">
Fonts are always fetched in CORS mode.
That's the spec — even for same-origin fonts.

Without crossorigin on the preload:
❌ Browser downloads the font (preload).
❌ CSS @font-face triggers another fetch (CORS).
❌ Font downloaded twice. Worse than no preload.

With crossorigin:
✅ One fetch, cached, used by CSS.
✅ No duplicate request.

⚠️ as="font" is required.
⚠️ type="font/woff2" helps older browsers skip.
⚠️ Preload only the weights you use above the fold.

Don't preload everything. The mistake of "add preload to all my CSS/JS/images" makes pages slower, not faster. Each preload is a claim on bandwidth — the browser downloads all of them in parallel, which slows down each one individually. Preload should highlight 1–3 critical resources, not duplicate every <img> and <script> on the page. If you can't name exactly why a resource is preloaded, remove it. The browser's default discovery is good; preload is for the few cases where the default is late.

⚠️ Common mistakes

The resource-hint mistakes that cost real time.

1. Preloading too many resources

Competes for bandwidth. Fix: 1–3 preloads, only critical resources.

2. Preloading fonts without crossorigin

Font downloaded twice. Fix: add crossorigin always for fonts.

3. Missing as attribute

Browser doesn't know priority or type. Fix: as="font", as="image", as="style".

4. Preconnecting to every domain

Sockets are expensive. Fix: 2–3 preconnects max — the most critical third parties.

5. Preloading resources used below the fold

Wastes bandwidth on what the user might not see. Fix: preload only above-the-fold resources.

6. Prefetching every page

Downloads pages the user may never visit. Fix: prefetch only the most likely next step.

7. Confusing preload and prefetch

preload = this page, now. prefetch = next page, later. Fix: match the hint to the intent.

8. No metrics before and after

Adding hints without measuring. Fix: check Lighthouse or WebPageTest before and after each change.

❓ Frequently asked

What is rel=preload?

rel='preload' on a link element tells the browser to download a resource as early as possible — before the browser would normally discover it. Use it for critical resources needed for first paint: fonts, the main hero image, the primary CSS file. Add as='font', as='image', as='style' to tell the browser what type of resource it is. Without as, the browser downloads the file but doesn't prioritize it correctly. Preload should be used sparingly — too many preloads compete for bandwidth and slow down everything.

What is rel=preconnect?

rel='preconnect' on a link element tells the browser to establish a connection (DNS lookup + TCP handshake + TLS negotiation) to a domain before it actually needs to fetch from it. Use it for third-party domains you will definitely fetch from: Google Fonts, a CDN, an analytics endpoint, a payment processor. Each connection saves 100-300ms of round-trip time. Preconnect is expensive — each one opens a socket — so limit to 2-3 domains.

What is the difference between preload and prefetch?

preload fetches a resource needed for the current page, with high priority. prefetch fetches a resource for a future navigation, with low priority. Preload says 'we need this now'; prefetch says 'we will need this later, download in idle time.' Use preload for the current page's critical resources. Use prefetch for the next page in a flow — the checkout page after cart, the article after a list.

What is dns-prefetch?

dns-prefetch does only the DNS lookup for a domain — the first step of a connection. It's cheaper than preconnect (no socket opened) but saves less time (only ~20-120ms instead of 100-300ms). Use it as a fallback for older browsers that don't support preconnect, or for domains you'll probably fetch from but aren't sure about. The common pattern: use both — preconnect for the main third-party domain, dns-prefetch for secondary ones.

Should I preload my fonts?

Yes, but carefully. Fonts are critical for first paint — if the font isn't loaded, the page shows a fallback font, then jumps when the real font loads. Preload the font file with as='font' and crossorigin. The crossorigin attribute is required for fonts, even same-origin — fonts are fetched in CORS mode. Preload only the font weights and styles you actually use above the fold. Preloading 6 font files is worse than preloading 1.

How many preloads is too many?

Three to five is a reasonable ceiling. Each preload competes for bandwidth with other resources — including the HTML, CSS, and JavaScript that actually block rendering. Preloading too many resources causes the browser to download them all in parallel, which slows down each individual download. The rule: preload only resources critical to first paint, that the browser wouldn't discover on its own until later.

🔗 Related

← All HTML problems
Problem solved · HTML