Preload, Prefetch, Preconnect: A Practical Guide to Resource Hints in WordPress

Three <link> tags. Nearly identical names. And a surprising number of WordPress sites using them backwards.

It’s easy to see why. Preload, prefetch, and preconnect sound like one idea wearing three different hats. They’re not, and swapping one for another can quietly make a page slower.

So instead of dictionary definitions, let’s take one ordinary site and figure out which hint goes where.

The site we’re fixing

It’s a small agency site built with Elementor. Big background photo in the hero. Inter from Google Fonts for all the text. Google Analytics, plus one of those chat bubbles in the bottom corner.

Nothing unusual. But watch what the browser goes through when someone lands on the homepage.

It reads the HTML and spots the stylesheets right away. The font and the hero photo, though, are hiding inside that CSS. The browser won’t know they exist until the CSS has arrived and been read, and on a phone, that gap is where your Largest Contentful Paint (LCP) suffers.

Resource hints are how you tip the browser off early. Here’s the cheat sheet before we get into each one:

HintWhat it doesBest for
preconnectOpens a connection to another domain earlyCritical third-party origins on the current page
dns-prefetchLooks up a domain’s address earlyLess urgent third-party origins
preloadDownloads a specific resource earlyCritical resources needed on the current page
prefetchFetches something at low priority for later useResources or pages likely to be needed next

Preconnect: the Google Fonts problem

Inter lives on fonts.gstatic.com, a different server. Before a single byte of font data moves, the browser has to find that server, connect to it, and agree on encryption. That’s a lot of back-and-forth before anything useful happens.

Preconnect gets that paperwork done early:

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

That crossorigin at the end isn’t decoration. Fonts get requested in CORS mode, which runs over its own connection. Skip the attribute and the browser prepares a connection the font can’t use, then builds another one when the font request shows up. It’s one of the most common mistakes with this hint.

What about analytics and the chat bubble? I’d leave them out. Open connections aren’t free, and Chrome drops an idle preconnect after roughly 10 seconds anyway. The chat widget usually loads later than that. (web.dev has a good explainer on the tradeoff.)

So: preconnect only for the few outside servers the first view really depends on. None for your own domain, since the browser is already talking to it.

DNS-prefetch: for the stuff that can wait

Analytics and the chat bubble still come from other domains, so they can get a smaller favor. DNS-prefetch only looks up the address and stops there.

<link rel="dns-prefetch" href="https://www.googletagmanager.com">

Tiny saving, tiny cost. Fine for scripts that load a bit later.

Side note: WordPress can add dns-prefetch hints on its own for external hosts that your scripts and styles load from. Worth a quick look at your page source before adding your own.

Preload: the hero photo

Now the part that actually moves LCP on our site.

The hero is a CSS background, so by default the browser grabs it late. Preload tells it: this file, this page, go get it now.

<link rel="preload" as="image"
      href="/wp-content/uploads/hero-1200.webp"
      imagesrcset="/wp-content/uploads/hero-600.webp 600w, /wp-content/uploads/hero-1200.webp 1200w"
      imagesizes="100vw"
      fetchpriority="high">

Two attributes in there deserve a sentence each. Without imagesrcset and imagesizes, a phone would get the same 1200px file as a desktop monitor. And fetchpriority="high" matters because preload moves the request earlier but doesn’t automatically make it important. For the LCP image, you want early and important.

If you self-host Inter, the font can be preloaded too:

<link rel="preload" href="/wp-content/uploads/fonts/Inter-Regular.woff2" as="font" type="font/woff2" crossorigin>

Check three things here. as has to be there. So does crossorigin, even though the file sits on your own server. And the URL must match your CSS exactly, because to a browser Inter-Regular.woff2?ver=1.2 is a different file from Inter-Regular.woff2.

Also, if the site pulls in five font families, deal with that first. Heavy fonts drag down Core Web Vitals whether you preload them or not.

Don’t preload the whole page

This is where preload goes sideways. Everyone wants their stuff loaded first, so everything gets preloaded, and the browser ends up back at square one with a longer to-do list.

Skip anything below the fold. Skip lazy-loaded images. Skip a plain <img> near the top of the HTML, because the browser finds that on its own almost instantly.

Chrome will flag your leftovers, by the way. A preloaded file that goes unused for a few seconds triggers a warning in the DevTools console.

If the hero is a normal image

Different site, and the hero is a regular <img> tag? Then preload is usually overkill. Put fetchpriority="high" on the image and move on.

<img src="hero.webp" fetchpriority="high" alt="..." width="1200" height="600">

Since version 6.3, WordPress tries to do this for you by guessing which image is the LCP element. Page builders sometimes throw that guess off, so view the source and check which image actually got the attribute. Google’s Fetch Priority guide goes deeper.

Prefetch: one page ahead

Prefetch plays a different game. It’s not about the page on screen. It’s about the next one.

The browser downloads the file when it has nothing better to do, at low priority:

<link rel="prefetch" href="/wp-content/themes/mytheme/checkout.js">

Our agency site doesn’t have an obvious next step, so prefetch won’t do much there. A shop is different. People on the cart page mostly head to checkout, so fetching the checkout script ahead of time makes sense.

Guess wrong, though, and it’s wasted data. And never use prefetch for something the current page needs. Low priority is the last thing that file wants.

WordPress 6.8 already prefetches

A lot of people missed this one. Since WordPress 6.8, core ships with speculative loading turned on. When a visitor starts clicking a link, the next page gets prefetched a moment early. It stays off for logged-in users and on sites without pretty permalinks, and the 6.8 announcement has the rest.

For many sites, that means a separate “instant page” plugin may no longer be necessary for basic internal prefetching. For more aggressive behavior, including prerendering, there’s the Speculative Loading plugin from the WordPress Performance Team.

Caching helps here too, since a prefetched page that’s already cached takes far less server work. One more reason WordPress caching matters. And for links that shouldn’t be prefetched (logout, add to cart), there’s the no-prefetch class.

Putting it into WordPress

Please don’t hand-edit header.php. A theme update erases it, and duplicates sneak in. WordPress has two filters for exactly this.

Preconnect and dns-prefetch go through wp_resource_hints, in your child theme’s functions.php or a snippets plugin:

add_filter( 'wp_resource_hints', function( $urls, $relation_type ) {

    if ( 'preconnect' === $relation_type ) {
        $urls[] = array(
            'href' => 'https://fonts.gstatic.com',
            'crossorigin',
        );
    }

    if ( 'dns-prefetch' === $relation_type ) {
        $urls[] = 'https://www.googletagmanager.com';
    }

    return $urls;
}, 10, 2 );

Preload goes through wp_preload_resources, added in WordPress 6.1:

add_filter( 'wp_preload_resources', function( $resources ) {

    // Inter font, used on every page
    $resources[] = array(
        'href'        => get_stylesheet_directory_uri() . '/assets/fonts/Inter-Regular.woff2',
        'as'          => 'font',
        'type'        => 'font/woff2',
        'crossorigin' => 'anonymous',
    );

    // Hero background, homepage only
    if ( is_front_page() ) {
        $img = get_stylesheet_directory_uri() . '/assets/img/';

        $resources[] = array(
            'href'          => $img . 'hero-1200.webp',
            'as'            => 'image',
            'imagesrcset'   => $img . 'hero-600.webp 600w, ' . $img . 'hero-1200.webp 1200w',
            'imagesizes'    => '100vw',
            'fetchpriority' => 'high',
        );
    }

    return $resources;
} );

That is_front_page() line saves every blog reader from downloading a homepage photo they’ll never see. Easy to forget. Full parameter lists live in the reference for wp_resource_hints and wp_preload_resources.

Before pasting any of this, hit Ctrl+U on your page and search for rel="pre. Themes and plugins often add hints already. On a site running FastPixel, DNS prefetching, preconnect hints, and LCP-related prioritization are handled automatically, so you’d only be filling gaps.

Checking your work

A bad hint doesn’t crash anything. It just sits there. So test before and after.

In DevTools, open the Network tab. Does the preloaded file start earlier than it used to? Switch on the Priority column to see how the browser really ranks it. Then run PageSpeed Insights on mobile and compare LCP and First Contentful Paint (FCP).

No change? Delete the hint. And while you’re in there, hunt for fossils, like a preconnect to fonts.googleapis.com left over from before you self-hosted your fonts.

The bottom line

For the agency site we used as example, the final list is short. Preconnect to Google Fonts (or self-host and drop it), dns-prefetch for analytics, preload for the hero background, and let WordPress handle prefetching for internal links.

That’s typical. Most sites need a few careful hints, not a pile of them.

Using FastPixel? You don’t need to worry about any of this, resource hints and loading priorities are fully handled automatically by the plugin.

FAQs

What’s the difference between preload and prefetch?

Preload is for a file the current page needs, fetched early. Prefetch is for something the next page might need, fetched at low priority.

How many files should I preload?

As few as possible. Only files that are critical and that the browser would otherwise find late.

Do I need a prefetch plugin on WordPress 6.8 or newer?

Usually not for basic internal navigation. Core already handles speculative prefetching for eligible links. The Speculative Loading plugin is there if you want prerendering or more aggressive settings.

Can resource hints make my site slower?

Yes. Too many preloads compete with each other, unused preconnects waste resources, and aggressive prefetching eats into mobile data.

Enjoyed reading? Spread the word!
Bianca Rus
Bianca Rus
Articles: 33
en_USEnglish