2026年11月12日

2026年11月12日

Add preload, prefetch and preconnect in WordPress with Core Filters

This article is a localized edition of the Japanese original. Read the Japanese original

preload and prefetch are hints that tell the browser to fetch a resource early. In WordPress, the filters built into core let you print them in the <head> with just a few lines in functions.php. This article explains when to use each hint, how to write them with WordPress filters, and how to check that they work.

The output of the code was verified on WordPress 6.9 (as of October 2026).

preload vs. prefetch vs. preconnect

Hint Target When to use it
preload Resources used on the current page Web fonts that are discovered late because they are referenced from CSS, large above-the-fold images
prefetch Resources used on the next page A page most visitors open next. Low priority, fetched when the browser is idle
preconnect A connection to an external server When you load resources from another domain, such as Google Fonts
dns-prefetch DNS resolution for an external domain When you want only a lighter preparation than preconnect

If you preload resources that are not used, you waste bandwidth and delay other resources. Resources the browser finds right away, such as a style.css loaded near the top of the <head>, do not need preloading. Limit it to resources that are essential for rendering but are discovered late.

What WordPress already outputs

Before adding your own hints, check what WordPress prints automatically so you do not duplicate it.

  • dns-prefetch: when scripts or styles are loaded from external domains, WordPress prints a dns-prefetch for those domains
  • Speculative loading (WordPress 6.8 and later): for logged-out visitors on sites whose permalink setting is anything other than "Plain", WordPress prints instructions (Speculation Rules API) to fetch linked pages in advance. By default it uses prefetch with a conservative setting that fetches when the visitor starts to click a link
  • Image fetchpriority (WordPress 6.3 and later): WordPress adds fetchpriority="high" to the img tag it judges to be the main above-the-fold image

View the page source and search for rel='preload', rel='dns-prefetch' and speculationrules to see what is currently output.

Output preload hints (wp_preload_resources)

From WordPress 6.1, returning an array from the wp_preload_resources filter prints <link rel='preload'> near the top of the <head>. The supported attributes are href, as, type, crossorigin, media, imagesrcset, imagesizes and fetchpriority (6.6 and later).

Here is an example that preloads a web font bundled with the theme. Add it to your child theme's functions.php.

<?php
add_filter( 'wp_preload_resources', function ( $resources ) {
	$resources[] = array(
		'href'        => get_theme_file_uri( 'fonts/noto-sans-jp-400.woff2' ),
		'as'          => 'font',
		'type'        => 'font/woff2',
		'crossorigin' => 'anonymous',
	);
	return $resources;
} );

The output looks like this:

<link rel='preload' href='https://example.com/wp-content/themes/mytheme/fonts/noto-sans-jp-400.woff2' as='font' type='font/woff2' crossorigin='anonymous' />

Keep these points in mind:

  • Preloading a font requires crossorigin, even for a file on the same domain. Without it, the font is downloaded a second time, separately from the preloaded file
  • Make href exactly the same URL you use in the CSS @font-face rule. Even a difference in the query string makes it a different resource
  • get_theme_file_uri() returns the child theme's URL if the file exists in the child theme, and the parent theme's URL otherwise

If the front page has a large above-the-fold image, use a conditional so the hint is printed only on that page.

<?php
add_filter( 'wp_preload_resources', function ( $resources ) {
	if ( is_front_page() ) {
		$resources[] = array(
			'href'          => get_theme_file_uri( 'images/hero.webp' ),
			'as'            => 'image',
			'fetchpriority' => 'high',
		);
	}
	return $resources;
} );

If the image is displayed with an img tag and WordPress already adds fetchpriority="high" to it, this hint is often unnecessary. It tends to help most with images the browser cannot find just by reading the HTML, such as CSS background images.

Output preconnect, dns-prefetch and prefetch hints (wp_resource_hints)

The wp_resource_hints filter (WordPress 4.6 and later) lets you add URLs per hint type. It is called with one of dns-prefetch, preconnect, prefetch or prerender as the second argument, $relation_type.

<?php
add_filter( 'wp_resource_hints', function ( $urls, $relation_type ) {
	if ( 'preconnect' === $relation_type ) {
		// Connect early to the host that serves Google Fonts font files
		$urls[] = array(
			'href' => 'https://fonts.gstatic.com',
			'crossorigin',
		);
	}
	if ( 'prefetch' === $relation_type && is_front_page() ) {
		// Fetch in advance a page that many visitors open from the front page
		$urls[] = home_url( '/contact/' );
	}
	return $urls;
}, 10, 2 );

The output is:

<link href='https://fonts.gstatic.com' crossorigin rel='preconnect' />
<link rel='prefetch' href='https://example.com/contact/' />

If you do not pass 2 as the fourth argument to add_filter(), $relation_type is not passed and you get an error. Keeping a preconnect connection open has a cost, so use it only for the few external domains you actually load resources from.

Tune next-page prefetching with speculative loading

From WordPress 6.8, core handles prefetching for links across the whole site. Adjusting its settings takes less work than listing individual pages with prefetch.

To start prefetching earlier, change eagerness with the wp_speculation_rules_configuration filter.

<?php
add_filter( 'wp_speculation_rules_configuration', function ( $config ) {
	if ( is_array( $config ) ) {
		$config['eagerness'] = 'moderate'; // The default is conservative (when the click starts)
	}
	return $config;
} );

For logged-in visitors, and on sites whose permalink setting is "Plain", $config is null and no prefetch rules are printed. The example above does nothing in that case.

Exclude pages that should not be prefetched, such as the cart or checkout, with the wp_speculation_rules_href_exclude_paths filter.

<?php
add_filter( 'wp_speculation_rules_href_exclude_paths', function ( $paths ) {
	$paths[] = '/cart/*';
	return $paths;
} );

To exclude only specific links, add the no-prefetch class to the link or a parent element. Links with rel="nofollow" are not prefetched either.

Sending preload as an HTTP header

preload can be specified not only with an HTML <link> but also with an HTTP Link response header. To add it to WordPress pages, send it from the send_headers action.

<?php
add_action( 'send_headers', function () {
	$font = get_theme_file_uri( 'fonts/noto-sans-jp-400.woff2' );
	header( 'Link: <' . esc_url_raw( $font ) . '>; rel=preload; as=font; type="font/woff2"; crossorigin', false );
} );

Passing false as the second argument to header() adds the header without overwriting the other Link headers WordPress sends (such as the REST API discovery link). At send_headers, WordPress has not yet decided which page to show, so conditionals such as is_front_page() do not work. If you need different hints per page, use wp_preload_resources from the earlier section.

Writing Header set Link inside <FilesMatch "\.(js)$"> in .htaccess has no effect. FilesMatch only adds the header to responses whose file name matches, that is, to the JS file's own response, not to the HTML page that needs the resource.

Check that it works

  1. View the page source and check that <link rel='preload'> and the other hints appear as intended. If you use a page cache, clear it first
  2. Reload with the "Network" tab of your browser's developer tools open, and check that preloaded resources load early and only once. If a font loads twice, suspect a missing crossorigin or a URL mismatch
  3. Check the "Console" tab for a warning that a preloaded resource was not used (was preloaded using link preload but not used within a few seconds). If it appears, the hint is not needed on that page, so remove it with a conditional
  4. Compare LCP (Largest Contentful Paint, the time until the largest content is displayed) before and after in PageSpeed Insights or Lighthouse

Speed varies with the network and device, so compare several runs instead of judging from one measurement.

Summary

  • Use preload for the current page, prefetch for the next page, and preconnect to prepare connections to external servers
  • Print preload with wp_preload_resources, and preconnect, dns-prefetch and prefetch with wp_resource_hints
  • Add crossorigin to font preloads and make the URL match the CSS
  • Tune prefetching of pages on your site through the speculative loading settings in WordPress 6.8 and later
  • Adding a Link header with FilesMatch in .htaccess does not reach the HTML. To send it as a header, use send_headers
  • Use the developer tools to confirm resources load early and once, with no unused-preload warning

Questions about WordPress? The publisher of this site is based in Japan and replies in Japanese. Contact (Japanese)

お気軽にご相談ください

お見積りへ お問い合わせへ
▲