Prefetching and related resource hints let modern browsers discover and start fetching critical third-party hosts and assets earlier in the page lifecycle. WordPress exposes a lightweight API and filter that let you add dns-prefetch, preconnect, prefetch and prerender hints from PHP so they appear in the HTML head. This article explains every practical detail you need: what each hint does, how WordPress expects them, safe and robust PHP examples, common pitfalls, and advanced patterns (like deriving hosts from enqueued scripts and adding crossorigin where needed).
Contents
Quick overview: what each resource hint does
rel | Purpose |
dns-prefetch | Resolve DNS early. Fastest, lowest cost asks the browser to resolve the hostname ahead of time. Use for hosts you will contact soon but not immediately. |
preconnect | Establish connection early. Starts DNS, TCP and optionally TLS handshake. Use for origins you will contact immediately (e.g., fonts, critical CDNs). |
prefetch | Fetch resource for later use. Browser may fetch and cache resources for future navigation or non-critical use. Good for next-page resources or large deferred assets. |
prerender | Render an entire page in the background. Aggressive, high cost use only when you are confident user will navigate to that page. |
WordPress support and the filter to use
WordPress provides a resource-hints API and a filter hook named wp_resource_hints. Themes and plugins add URLs to the array passed to that filter. WordPress will output link tags for the given relation type in the head when wp_resource_hints() runs (this is available since WordPress 4.6). The filter signature is:
- apply_filters( wp_resource_hints, array urls, string relation_type )
- Your callback must return the (possibly modified) array of URLs for that relation type.
Basic example: add a single preconnect using the filter
The canonical and safest way to add a hint is to add your host to the array only when the relation type matches, then return the array. This prevents your code from outputting the same URL for the wrong relation (and avoids duplicate tags).
lt?php add_filter( wp_resource_hints, mytheme_add_preconnect, 10, 2 ) function mytheme_add_preconnect( hints, relation_type ) { // Only add hosts for the preconnect relation type if ( preconnect === relation_type ) { // Add the origin you want to preconnect to hints[] = https://fonts.gstatic.com } return hints } ?gt
Notes on the example
- WordPress expects a list of URL strings in hints. For dns-prefetch you may prefer protocol-relative origins like //example.com, but fully-qualified URLs (including https://) are also acceptable.
- Keep the relation-type check strict (preconnect === relation_type) so your URL only appears with the right rel attribute.
Example: add dns-prefetch and preconnect for a CDN derived from enqueued scripts
Instead of hardcoding hosts, you can inspect enqueued scripts and styles (or registered ones) and add hints dynamically. The snippet below shows how to add a dns-prefetch for every unique host used by enqueued assets, and a targeted preconnect for a specific host (e.g., where fonts are served).
lt?php add_filter( wp_resource_hints, mytheme_hints_for_enqueued_assets, 10, 2 ) function mytheme_hints_for_enqueued_assets( hints, relation_type ) { // Only run on front-end requests (avoid admin screens) if ( is_admin() ) { return hints } // Well collect unique hosts hosts = array() // Inspect enqueued scripts global wp_scripts if ( isset( wp_scripts ) is_object( wp_scripts ) ) { foreach ( wp_scripts->queue as handle ) { src = wp_scripts->registered[ handle ]->src ?? if ( src ) { src = set_url_scheme( src ) // make sure it has scheme url_parts = wp_parse_url( src ) if ( ! empty( url_parts[host] ) ) { hosts[] = url_parts[host] } } } } // Inspect enqueued styles global wp_styles if ( isset( wp_styles ) is_object( wp_styles ) ) { foreach ( wp_styles->queue as handle ) { src = wp_styles->registered[ handle ]->src ?? if ( src ) { src = set_url_scheme( src ) url_parts = wp_parse_url( src ) if ( ! empty( url_parts[host] ) ) { hosts[] = url_parts[host] } } } } // Deduplicate hosts = array_unique( hosts ) foreach ( hosts as host ) { // For dns-prefetch, protocol-relative origin is common if ( dns-prefetch === relation_type ) { hints[] = // . host } // If you have a known critical host (like fonts), add preconnect if ( preconnect === relation_type fonts.gstatic.com === host ) { hints[] = https:// . host } } return hints } ?gt
Why build the origin like that?
- dns-prefetch commonly uses protocol-relative URIs (starting with //) so the browser will use the current pages scheme including the scheme (https://) also works.
- preconnect should usually be an absolute origin with scheme, as the browser may need to perform TLS handshakes correctly.
When you need crossorigin on preconnect
For some cross-origin resources — most notably web fonts — the browser requires a crossorigin attribute on the preconnect link so the servers TLS/TCP connection and subsequent fetches behave correctly. The wp_resource_hints filter only supplies URLs to WordPress it doesnt let you attach attributes per URL. If you need a crossorigin attribute you have two safe options:
- Output the tag manually in wp_head for the specific host you need with the correct crossorigin value.
- Use the filter to add the origin (so WordPress outputs the base hint) and also output an extra preconnect link with crossorigin manually (avoid duplicates by using guards).
Manual preconnect with crossorigin in wp_head (example)
lt?php // In functions.php or plugin file add_action( wp_head, mytheme_preconnect_with_crossorigin, 1 ) // early priority function mytheme_preconnect_with_crossorigin() { if ( is_admin() ) { return } // Output a preconnect with crossorigin for fonts.gstatic.com echo ltlink rel=preconnect href=https://fonts.gstatic.com crossorigingt } ?gt
Notes
- When you echo tags manually, be careful to output them early enough in the head to be useful — a low-number priority (like 1 or 5) is fine.
- If you also added the same origin via the wp_resource_hints filter, you may produce duplicate tags. Use a conditional guard, or prefer the manual approach only where crossorigin is required.
Use prefetch when you want the browser to fetch resources that are likely to be used soon (but not immediately). Use prerender to tell the browser to render a full page in the background — this is aggressive and should be used sparingly.
lt?php add_filter( wp_resource_hints, mytheme_prefetch_next_article, 10, 2 ) function mytheme_prefetch_next_article( hints, relation_type ) { // Example: prefetch the next posts permalink on single post views if ( is_single() prefetch === relation_type ) { next_post = get_next_post() if ( next_post ) { hints[] = get_permalink( next_post ) } } // Example: prerender the next page of a paginated listing (be careful!) if ( is_home() prerender === relation_type ) { next_page = get_query_var( paged ) ? intval( get_query_var( paged ) ) 1 : 2 hints[] = get_pagenum_link( next_page ) } return hints } ?gt
Best practices and hard-earned tips
- Only add hints that will likely be useful. Overhinting (adding many preconnects/prefetches) wastes bandwidth and can harm performance.
- Use relation-type checks. Always check relation_type in your filter and only add URLs for the appropriate relation.
- Sanitize inputs. Use set_url_scheme(), esc_url_raw(), or wp_parse_url() when you manipulate or reformat URLs.
- Avoid admin pages. Run the logic only on front-end requests (e.g., guard with is_admin()).
- Prefer origins for dns-prefetch and preconnect. These hints operate at the origin level dns-prefetch typically uses //host and preconnect often uses https://host.
- Remember crossorigin for cross-origin preconnects used by fonts. If a resource (fonts) requires crossorigin set to anonymous or use-credentials, ensure you output a preconnect with the attribute.
- Measure with real users. Use RUM (Real User Monitoring) or Lighthouse/DevTools to verify that your hints improve, not degrade, performance.
Troubleshooting common mistakes
- Adding full asset URLs for dns-prefetch: dns-prefetch is designed to be origin-level. If you pass a full file URL it may still work in some browsers, but using protocol-relative origin (//host) or origin with scheme is clearer.
- Duplicate tags: If both your theme and a plugin add the same hint, youll get duplicates. Check the returned hints and deduplicate if needed.
- Forgetting to return the array: Your callback must always return the modified hints array.
- Expecting immediate help for non-critical assets: prefetch and dns-prefetch do not guarantee the resource will be used immediately browser heuristics govern resource prioritization.
Putting it all together: a robust helper function
This final example is a reusable helper you can drop into a theme or plugin. It:
- Accepts an array of origins to preconnect to on the front-end
- Adds dns-prefetch for all origins when the relation type matches
- Adds preconnect for the same origins when requested
- Provides a small whitelist/blacklist mechanism to avoid accidental overhinting
lt?php // Example reusable helper: register origins and apply via the wp_resource_hints filter add_filter( wp_resource_hints, mytheme_register_resource_origins, 10, 2 ) function mytheme_register_resource_origins( hints, relation_type ) { if ( is_admin() ) { return hints } // Define a small, curated list of origins used by your theme/plugin. // Keep this list minimal — only hosts that are important. origins = array( https://fonts.gstatic.com, https://fonts.googleapis.com, https://cdn.example.com, ) // You could also make this list dynamic from options or constants. foreach ( origins as origin ) { // Normalize URL origin = set_url_scheme( origin ) if ( dns-prefetch === relation_type ) { // For dns-prefetch, prefer protocol-relative form parts = wp_parse_url( origin ) if ( ! empty( parts[host] ) ) { hints[] = // . parts[host] } } if ( preconnect === relation_type ) { // For preconnect, include the scheme hints[] = origin } // For prefetch/prerender you may add full resource URLs instead of origins. // Example (prefetch a known CSS file): if ( prefetch === relation_type false ) { // Add individual resource URLs here // hints[] = https://cdn.example.com/some-large-asset.js } } // Deduplicate and return hints = array_unique( hints ) // Optional sanitization hints = array_map( esc_url_raw, hints ) return hints } ?gt
Final operational notes (compatibility and measurement)
Resource hints are widely supported in modern browsers but are subject to browser heuristics. WordPress introduced the resource hints API in version 4.6. Always measure impact using Lighthouse, WebPageTest or Real User Monitoring — what helps one site can hurt another if misused. Keep preconnects and prefetches sparse and tied to real, measured needs.
References
- MDN: Preload, Prefetch and Preconnect pages
- Chrome Docs: Resource hints and Lighthouse
- WordPress Developer Reference: wp_resource_hints filter
|
Acepto donaciones de BAT's mediante el navegador Brave 🙂 |