Resource Hints and Preloading
1. Introduction
Resource hints are <link> elements placed in the <head> that instruct the browser to anticipate future network requests โ fetching, connecting to, or processing resources before they are actually needed. When used correctly, they can eliminate hundreds of milliseconds of render-blocking latency. This lesson covers preload, prefetch, preconnect, dns-prefetch, and the newer modulepreload, explaining when each one is appropriate and when it can hurt instead of help.
2. Concept
Resource Hint Types Compared
| rel Value | When Executed | Use For | Priority |
|---|---|---|---|
preload |
Immediately (current page) | Critical fonts, LCP image, CSS, above-fold scripts | High |
modulepreload |
Immediately (current page) | ES modules used on the current page | High |
prefetch |
Idle time (next navigation) | Resources needed for the next page the user will likely visit | Lowest |
preconnect |
Immediately (TCP+TLS handshake) | Third-party origins: CDNs, fonts, APIs | Medium |
dns-prefetch |
Immediately (DNS only) | Fallback for older browsers; many third-party origins | Low |
preload requires the as attribute to tell the browser the resource type. Without it, the browser cannot apply the correct Content Security Policy, compute request priority, or set correct Accept headers โ and the hint may be ignored entirely.3. Basic Example
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Resource Hints Demo</title>
<!-- 1. preconnect: establish connection to Google Fonts early -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<!-- 2. dns-prefetch: DNS-only for additional third-party origins -->
<link rel="dns-prefetch" href="https://analytics.example.com">
<!-- 3. preload: critical above-fold font (as="font" + crossorigin required) -->
<link
rel="preload"
href="/fonts/inter-var.woff2"
as="font"
type="font/woff2"
crossorigin
>
<!-- 4. preload: LCP hero image -->
<link
rel="preload"
href="/images/hero-1200.jpg"
as="image"
imagesrcset="/images/hero-600.jpg 600w, /images/hero-1200.jpg 1200w"
imagesizes="(max-width:600px) 100vw, 1200px"
>
<!-- 5. prefetch: resource needed on the next page -->
<link rel="prefetch" href="/product-detail.js">
<link rel="stylesheet" href="/styles.css">
</head>
<body>
<h1>Resource Hints Demo</h1>
<img
src="/images/hero-1200.jpg"
srcset="/images/hero-600.jpg 600w, /images/hero-1200.jpg 1200w"
sizes="(max-width:600px) 100vw, 1200px"
alt="Hero image"
width="1200" height="630"
fetchpriority="high"
>
</body>
</html>
4. How It Works
Step 1 โ preconnect for Third-Party Origins
Before a browser can download a resource from a new origin, it must perform DNS lookup, TCP handshake, and TLS negotiation โ which can take 200โ500 ms. rel="preconnect" performs all three steps early. Add crossorigin for origins that serve CORS resources (fonts, scripts from CDNs).
Step 2 โ preload for Critical Current-Page Resources
rel="preload" tells the browser to fetch a resource at high priority immediately, even before the parser encounters it in the HTML. Use it for: the LCP image, critical above-fold fonts (to avoid FOUT), and render-blocking CSS not in the critical path.
Step 3 โ prefetch for Next-Page Resources
rel="prefetch" requests the browser to download a resource at lowest priority during idle time, storing it in the HTTP cache. Use it for resources you are confident the user will need on their next navigation. Do not use it for current-page critical resources โ it has lower priority than preload.
Step 4 โ dns-prefetch as Fallback
rel="dns-prefetch" performs only the DNS lookup โ cheaper than preconnect but less effective. Use it alongside preconnect (browsers ignore one if they know the other) and for origins where you do not want a persistent connection kept open.
5. Real-World Example
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>TechStore | Laptops, Monitors, Accessories</title>
<!-- Preconnect: CDN for images, analytics, payment provider -->
<link rel="preconnect" href="https://cdn.techstore.com" crossorigin>
<link rel="preconnect" href="https://js.stripe.com">
<link rel="dns-prefetch" href="https://www.google-analytics.com">
<link rel="dns-prefetch" href="https://connect.facebook.net">
<!-- Preload: self-hosted font (crossorigin required even for same-origin fonts in some browsers) -->
<link rel="preload" href="/fonts/inter-v13-latin-regular.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="/fonts/inter-v13-latin-600.woff2" as="font" type="font/woff2" crossorigin>
<!-- Preload: LCP hero banner (responsive) -->
<link
rel="preload"
as="image"
href="/banners/summer-sale-1200.jpg"
imagesrcset="/banners/summer-sale-480.jpg 480w, /banners/summer-sale-800.jpg 800w, /banners/summer-sale-1200.jpg 1200w"
imagesizes="(max-width:480px) 100vw, (max-width:800px) 100vw, 1200px"
>
<!-- Preload: critical CSS (inlined in production; shown here for demo) -->
<link rel="preload" href="/css/critical.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="/css/critical.css"></noscript>
<!-- Prefetch: product detail page resources (user likely to browse) -->
<link rel="prefetch" href="/js/product-detail.js">
<link rel="prefetch" href="/css/product-detail.css">
<link rel="stylesheet" href="/css/main.css">
</head>
<body>
<h1>Summer Sale โ Up to 40% Off</h1>
<img
src="/banners/summer-sale-1200.jpg"
srcset="/banners/summer-sale-480.jpg 480w, /banners/summer-sale-800.jpg 800w, /banners/summer-sale-1200.jpg 1200w"
sizes="(max-width:480px) 100vw, (max-width:800px) 100vw, 1200px"
alt="Summer sale banner: up to 40% off selected laptops and monitors until 31 July"
width="1200" height="400"
fetchpriority="high"
>
</body>
</html>
6. Common Mistakes
❌ preload without the as attribute โ hint may be ignored
<link rel="preload" href="/fonts/inter.woff2">
✓ Always specify as, type, and crossorigin for fonts
<link rel="preload" href="/fonts/inter.woff2" as="font" type="font/woff2" crossorigin>
❌ Using prefetch for current-page critical resources
<link rel="prefetch" href="/css/main.css">
✓ Use preload for current-page resources; prefetch for next-page resources
<link rel="preload" href="/css/main.css" as="style">
7. Try It Yourself
▶ Test with Google PageSpeed Insights
8. Quick Reference
| rel | Priority | as Required? | crossorigin? | Use For |
|---|---|---|---|---|
| preload | High | Yes | For fonts and CORS | Critical current-page resources |
| modulepreload | High | No | Auto | ES module scripts |
| prefetch | Lowest | Optional | Optional | Next-page resources |
| preconnect | Medium | No | For CORS origins | Third-party origins (CDN, fonts, API) |
| dns-prefetch | Low | No | No | DNS-only warmup for many origins |