Resource Hints preload prefetch
dns-prefetch, preconnect, preload, prefetch, modulepreload — when each helps LCP/navigation and how to avoid over-fetching.
- javascript
- resource-hints
The network is often the long pole. Resource hints tell the browser what you’ll need soon so it can open connections or fetch early — or they waste bandwidth if you lie. These are mostly HTML/<link> (and HTTP Link headers), orchestrated from frontend architecture.
The menu
| Hint | Intent | Priority vibe |
|---|---|---|
dns-prefetch |
Resolve DNS early | cheap |
preconnect |
DNS + TCP + TLS | medium cost |
preload |
Fetch now for current navigation | high — competes with critical assets |
prefetch |
Likely next navigation | low |
modulepreload |
ES module graph for current page | high for modules |
<link rel="dns-prefetch" href="https://cdn.example.com" />
<link rel="preconnect" href="https://api.example.com" crossorigin />
<link rel="preload" href="/fonts/Inter.woff2" as="font" type="font/woff2" crossorigin />
<link rel="preload" href="/hero.avif" as="image" fetchpriority="high" />
<link rel="modulepreload" href="/assets/main.js" />
<link rel="prefetch" href="/next-page-data.json" as="fetch" crossorigin />
preload rules of thumb
- Only critical current-page resources (LCP image, render-blocking font you definitely use).
asmust match how it’ll be consumed or the browser may double-fetch.- Fonts need
crossorigineven when same-origin (anonymous CORS mode for fonts). - Over-preloading fights with your real critical CSS/JS budget.
// dynamic preload for LCP discovered late
const link = document.createElement('link');
link.rel = 'preload';
link.as = 'image';
link.href = lcpUrl;
document.head.appendChild(link);
prefetch for next page
<link rel="prefetch" href="/product/42" />
Good after hover/intent on SPA route targets or pagination “next.” Browsers deprioritize; still don’t prefetch huge videos for every user on 2G.
In SPAs, data prefetch on link hover is often better in JS (fetch + cache) than blind full document prefetch.
preconnect budget
Each preconnect costs sockets and CPU. Cap to a few critical origins (CDN, API, font host). dns-prefetch alone is cheaper when you only need DNS.
vs Early Hints / HTTP Link
CDNs and servers can send Link: </app.css>; rel=preload; as=style before HTML finishes. Same semantics; earlier on slow TTFB paths.
Measuring
Use Lighthouse/WebPageTest: did LCP improve, or did you just download more? Watch unused preloads warnings in Chrome.
Interview answer (out loud)
“dns-prefetch and preconnect warm origins; preload fetches critical current navigation assets with correct as; modulepreload is for the module graph; prefetch is speculative for the future. I preload sparingly for LCP and fonts, preconnect only key origins, and verify with performance tools so hints don’t steal bandwidth.”
as values that matter
Common as tokens: script, style, image, font, fetch, document. Wrong as can make the preload unusable and waste the download.
<link rel="preload" href="/app.js" as="script" />
<link rel="preload" href="/app.css" as="style" />
fetchpriority
<link rel="preload" as="image" href="hero.jpg" fetchpriority="high" />
Helps LCP competition among images; still don’t mark everything high.
SPA route prefetch example
link.addEventListener('pointerenter', () => {
import('./pages/Settings.js'); // module prefetch via dynamic import
}, { once: true });
Complements <link rel=prefetch> for code-split chunks.
Further reading
Related
Related guides
- AbortControllerCancel fetch and other async work with AbortController and AbortSignal — timeouts, race conditions, and cleanup when components unmount.
- Array find, some, every, includesShort-circuiting array predicates: find, findIndex, some, every, and includes — when to use each and common interview traps.
- Array map, filter, reducemap, filter, and reduce as the core transform toolkit — immutability, chaining costs, reduce patterns, and when a plain loop is clearer.
- Arrow Functions Deep DiveLexical this, no arguments object, no construct, concise bodies — when arrows help and when methods and generators need classic functions.
- Async Iteration and for await...ofAsync iterables, for await...of, and streaming data — how async iterators differ from Promise.all and when to use each.