WordPress 6.8 introduces speculative loading, which can lead to near-instant page load times by loading URLs before the user navigates to them. The feature relies on the Speculation Rules API, a web platform feature that allows defining rules for which kinds of URLs to prefetch or prerender, and how early such speculative loading should occur.
Please refer to the speculative loading announcement post for additional information about the Speculation Rules API An API or Application Programming Interface is a software intermediary that allows programs to interact with each other and share data in limited, clearly defined ways. and related prior art in WordPress Core Core is the set of software required to run WordPress. The Core Development Team builds WordPress..
Context
Prior to being implemented in WordPress Core, the feature has been successfully used on over 50,000 WordPress sites via the Speculative Loading feature plugin, which has been ported over to Core now, with a few modifications. Based on data queried from the HTTP Archive and Chrome User Experience Report (CrUX) datasets over all the time since the plugin A plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory https://wordpress.org/plugins/ or can be cost-based plugin from a third-party launched, the sites that enabled speculative loading improved their Largest Contentful Paint (LCP) passing rate by ~1.9% at the median which, while it may seem a small number, is a huge boost for a single feature, considering that a lot of sites with various performance implications contribute to the data.
The Speculation Rules API was first introduced in early 2023 and has seen ever increasing usage since then. Today, over 8% of Chrome navigations rely on Speculation Rules. A related significant launch happened a few months ago when Cloudflare enabled speculative loading at large scale via its Speed Brain feature.
The Speculation Rules API is supported by Chrome, Edge, and Opera so far, which means the vast majority of end users browsing the web can benefit from its capabilities. For users of browsers without support for the API, there are no adverse effects, since the Speculation Rules API is a progressive enhancement Enhancements are simple improvements to WordPress, such as the addition of a hook, a new feature, or an improvement to an existing feature.. Browsers without support simply ignore its presence, i.e. sites maintain the same behavior as before.
Default behavior and customization
The WordPress Core implementation enables speculative loading by default in the frontend of all sites, except when a user is logged in or when a site has pretty permalinks disabled. URLs are prefetched with conservative eagerness: this means that prefetching is triggered when a user starts to click on a link. While this is typically only a fraction of a second before the actual navigation occurs, it is still enough to lead to a notable performance improvement.
This default of prefetch
with conservative
eagerness is used as a reasonable starting point to enable speculative loading at the scale of WordPress. It is in line with the configuration that Cloudflare uses in its speculative loading feature, and it minimizes the chance of any speculative loads without a subsequent navigation to the URL A specific web address of a website or web page on the Internet, such as a website’s URL www.wordpress.org. The Speculative Loading plugin uses a default of prerender
with moderate
eagerness, which leads to a larger performance improvement due to the speculative load being triggered earlier as well as prerendering the URL, but also has tradeoffs related to certain client-side behavior inadvertently being triggered even in case the user never ends up navigating to the URL.
Customization via actions and filters
Excluding URL patterns from speculative loading
When a URL is prefetched, the server response is loaded before the user navigates to it. In most cases, this is not an issue since server responses for frontend URLs do not typically change the state of the site in any way. However, there may be plugins that use the pattern of so-called “action URLs”, where simply navigating to a specific URL (with a GET
request) a state change occurs—for example on an e-commerce WordPress site, it could be adding a product to the shopping cart or marking an item as a favorite. It is worth noting that this is an antipattern, since state changes should typically be triggered only by POST
requests, e.g. via form submissions, and GET
requests are supposed to be “idempotent”. Despite that, plugins that use this pattern should ensure that such URLs are excluded from prefetching and prerendering. In the case of conservative
eagerness, this should not be an issue since it’s almost guaranteed the user will also navigate to the URL. But for sites that use a more eager configuration there is a chance the navigation will never occur, which is why excluding such URLs is important.
By default, any URLs that include query parameters are excluded from prefetching and prerendering automatically, which should cater for the majority of such action URLs. However, in case a plugin is implementing its own rewrite rules for these URLs instead of using custom query parameters, they can use the wp_speculation_rules_href_exclude_paths
filter Filters are one of the two types of Hooks https://codex.wordpress.org/Plugin_API/Hooks. They provide a way for functions to modify data of other functions. They are the counterpart to Actions. Unlike Actions, filters are meant to work in an isolated manner, and should never have side effects such as affecting global variables and output. to provide URL patterns to exclude.
This example ensures that any URLs with a path starting in “/cart/” will be excluded from speculative loading, regardless of whether it’s prefetch
or prerender
:
add_filter(
'wp_speculation_rules_href_exclude_paths',
function ( $href_exclude_paths ) {
$href_exclude_paths[] = '/cart/*';
return $href_exclude_paths;
}
);
All URL patterns provided should follow the URL Pattern web specification, and they will all be considered relative to the frontend of the site. For sites where the home URL is in a subdirectory, WordPress will automatically prefix the corresponding path segment so that plugin developers do not need to worry about that.
While WordPress Core’s default behavior is to prefetch URLs, sites may opt in to prerendering URLs. This leads to a significant performance boost, but also has additional implications on the speculatively loaded URLs, since even their client-side code will be loaded. If a site contains any client-side logic that should only run once the user actually navigates to the URL, it needs to check for whether the site is being prerendered first and only trigger such logic once the navigation has occurred (see “Detect prerender in JavaScript” documentation). A common use-case for that is analytics tooling (see “Impact on analytics” documentation). Many popular providers already support prerendering, so no change is necessary. But if your site or your plugin includes such functionality on certain URLs and you haven’t updated the JavaScript JavaScript or JS is an object-oriented computer programming language commonly used to create interactive effects within web browsers. WordPress makes extensive use of JS for a better user experience. While PHP is executed on the server, JS executes within a user’s browser. https://www.javascript.com/. logic to support prerendering yet, you can temporarily exclude the relevant URLs from prerendering specifically.
This example ensures that any URLs with a path starting in “/personalized-area/” will be excluded from prerender
speculative loading only:
add_filter(
'wp_speculation_rules_href_exclude_paths',
function ( $href_exclude_paths, $mode ) {
if ( 'prerender' === $mode ) {
$href_exclude_paths[] = '/personalized-area/*';
}
return $href_exclude_paths;
},
10,
2
);
Modifying the default speculative loading configuration
As mentioned before, WordPress sites are able to modify the default speculative loading configuration. For further improved performance, you may want the configuration to be more eager or to leverage prerendering. This can be achieved via the wp_speculation_rules_configuration
filter, which receives either an associative array with mode
and eagerness
keys to control the configuration, or null
to disable speculative loading for the current request.
The default value for the filter is array( 'mode' => 'auto', 'eagerness' => 'auto' )
, unless a user is logged-in or the site has pretty permalinks disabled, in which case the default value is null
. For both configuration parameters, the value auto signifies that WordPress Core will decide on the configuration, which as of today effectively leads to a mode
of prefetch
and an eagerness
of conservative
. Depending on various criteria such as the state of the Speculation Rules API and ecosystem support, the behavior may change in a future WordPress release.
Here is an example that uses the filter to increase the eagerness to moderate
. This will improve the performance benefits, while increasing the tradeoff for a speculative load without subsequent navigation:
add_filter(
'wp_speculation_rules_configuration',
function ( $config ) {
if ( is_array( $config ) ) {
$config['eagerness'] = 'moderate';
}
return $config;
}
);
The mode
value can be either auto
, prefetch
, or prerender
, and the eagerness
value can be either auto
, conservative
, moderate
, or eager
. The Speculation Rules API also defines another eagerness value of immediate
, however that value is strongly discouraged for document-level rules that speculatively load any URLs, so the WordPress Core API does not allow using it for its overall configuration.
If you wanted to opt for an even greater performance boost, here is an example that uses the filter to opt for prerender
with moderate
eagerness. This is similar to what the Speculative Loading feature plugin implements, and it can lead to a significant performance boost. Please keep in mind the effects of prerendering on client-side JavaScript logic explained in the previous section before enabling prerender
.
add_filter(
'wp_speculation_rules_configuration',
function ( $config ) {
if ( is_array( $config ) ) {
$config['mode'] = 'prerender';
$config['eagerness'] = 'moderate';
}
return $config;
}
);
As mentioned before, speculative loading is disabled by default for sites that do not use pretty permalinks. This is because the aforementioned exclusion of URLs with query parameters would not reliably apply anymore if even WordPress Core’s arguments used query parameters. There may however be cases where, as a site owner of a site without pretty permalinks, you are confident that your site is not using any of the problematic patterns that are the reason for this exclusion in the first place, or you already identified them and explicitly excluded URLs with the specific query parameters from being speculatively loaded. In that case, you could use the filter to enable speculative loading, as seen here:
add_filter(
'wp_speculation_rules_configuration',
function ( $config ) {
if ( ! $config && ! get_option( 'permalink_structure' ) ) {
$config = array(
'mode' => 'auto',
'eagerness' => 'auto',
);
}
return $config;
}
);
Please use caution when opting into speculative loading like this. WordPress Core’s defaults were carefully considered to cater for the majority of sites in a safe way, so only use this code snippet if you are confident it will not have adverse effects on your site.
Including additional speculation rules
The Speculation Rules API allows defining multiple rules to configure how the browser should speculatively load URLs. By default, WordPress Core only includes a single rule that handles all the aforementioned behavior. More advanced customization is possible by providing entirely new speculation rules in addition to Core’s main rule, which can be accomplished by using the wp_load_speculation_rules
action. The action receives an instance of the new WP_Speculation_Rules
class, which has validation mechanisms built in and can be amended as needed. By adding new rules, you can implement entirely custom configurations that will be applied on top of WordPress Core’s main rule.
Here is an example, which directly relates to the previous example that changes the default configuration to prerender
with moderate
eagerness. You may prefer not to change the default, but there may be specific URLs where you would like to enable prerender
with moderate
eagerness. You could add a custom URL-level speculation rule for that:
add_action(
'wp_load_speculation_rules',
function ( WP_Speculation_Rules $speculation_rules ) {
$speculation_rules->add_rule(
'prerender',
'my-moderate-prerender-url-rule',
array(
'source' => 'list',
'urls' => array(
'/some-url/',
'/another-url/',
'/yet-another-url/',
),
'eagerness' => 'moderate',
)
);
}
);
Taking this example further, maybe there is no easy way to provide a list of URLs, e.g. in case they change often or more URLs need to be added regularly. In that case, you consider using a document-level speculation rule that applies for all links that are marked with a specific class, or where a parent element has a specific class:
add_action(
'wp_load_speculation_rules',
function ( WP_Speculation_Rules $speculation_rules ) {
$speculation_rules->add_rule(
'prerender',
'my-moderate-prerender-optin-rule',
array(
'source' => 'document',
'where' => array(
'selector_matches' => '.moderate-prerender, .moderate-prerender a',
),
'eagerness' => 'moderate',
)
);
}
);
With this rule in place, users would be able to add a moderate-prerender
class to any block Block is the abstract term used to describe units of markup that, composed together, form the content or layout of a webpage using the WordPress editor. The idea combines concepts of what in the past may have achieved with shortcodes, custom HTML, and embed discovery into a single consistent API and user experience. that supports the advanced UI User interface for adding classes, and that way they could manually opt in any link on demand.
Please refer to the Speculation Rules API specification for details on what a rule definition can look like.
Customization via UI
The previous example already hints at how speculative loading can be customized via the UI. While a dedicated UI for the feature like it exists in the Speculative Loading feature plugin is out of scope for WordPress Core, many block types provide an “Additional CSS Cascading Style Sheets. class(es)” field in the “Advanced” panel in the block sidebar A sidebar in WordPress is referred to a widget-ready area used by WordPress themes to display information that is not a part of the main content. It is not always a vertical column on the side. It can be a horizontal rectangle below or above the content area, footer, header, or any where in the theme..
WordPress Core has built-in support for the CSS classes no-prefetch
and no-prerender
. You can add these to any block so that links within that block are opted out of prefetching or prerendering respectively. Note that no-prefetch
opts out of both, i.e. opts out of speculative loading entirely, since prefetching is part of prerendering. Please refer to the section about excluding URL patterns for guidance on when it may be useful to exclude URLs from prefetching or prerendering.
This mechanism makes it easy for advanced users to take granular control over speculative loading for specific blocks.
Summary and further reading
The speculative loading feature in WordPress 6.8 is a great win for performance of WordPress and the web overall, by starting the page load process even before the user navigation occurs. By fine-tuning it further based on your site’s needs, you can achieve even greater performance boosts than with the default configuration.
Please see the following links for further reading:
Props to @westonruter, @tunetheweb, @adamsilverstein, @joemcgill for review and proofreading.
#6-8, #dev-notes, #dev-notes-6-8, #feature-projects, #performance, #speculative-loading
You must be logged in to post a comment.