Resource Hints and Preloading

โ–ถ Try It Yourself

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
Note: 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.
Tip: Do not preload everything. Each unnecessary preload competes for bandwidth with truly critical resources. Audit with Chrome DevTools Lighthouse โ€” it flags both missing preloads and wasteful unused preloads.
Warning: A preloaded resource that is not used within 3 seconds of the window load event triggers a console warning in Chrome: “The resource was preloaded but not used.” This wastes bandwidth and signals a misconfiguration โ€” often caused by preloading resources with cache-busting hashes that don’t match the actual request.

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

9. Quiz

🧠 Test Yourself

Which resource hint should you use to preload a critical self-hosted font on the current page?





โ–ถ Try It Yourself