函数文档

wp_resource_hints()

💡 云策文档标注

概述

wp_resource_hints() 函数用于向浏览器输出资源提示,以优化网站性能,包括预获取、预渲染和预连接。它通过生成 HTML 链接标签,帮助浏览器提前执行 DNS 查询、建立连接或加载资源。

关键要点

  • 函数生成四种资源提示类型:dns-prefetch、preconnect、prefetch 和 prerender,分别用于 DNS 预解析、预连接、预获取和预渲染。
  • 默认情况下,dns-prefetch 使用 wp_dependencies_unique_hosts() 获取已入队脚本和样式的唯一主机列表。
  • 支持通过 wp_resource_hints 过滤器自定义或修改资源提示的 URL 和属性,允许开发者灵活控制输出。
  • 函数内部处理 URL 验证和转义,确保安全性,并针对不同关系类型调整 URL 格式(如协议相对 URL)。
  • 输出为 HTML 链接标签,直接插入到页面头部,以提升加载速度和用户体验。

代码示例

// 示例:使用 wp_resource_hints 过滤器移除特定 DNS 预获取
add_filter( 'wp_resource_hints', function( $urls ) {
    foreach ($urls as $key => $url) {
        if ( 'https://s.w.org/images/core/emoji/13.0.0/svg/' === $url ) {
            unset( $urls[ $key ] );
        }
    }
    return $urls;
} );

注意事项

  • 移除资源提示时,避免直接删除整个 wp_resource_hints 动作,以免影响性能优化;推荐使用过滤器进行精细控制。
  • 对于 WordPress 核心添加的资源提示(如 emoji SVG),可使用更未来的方式,如 emoji_svg_url 过滤器,以保持代码兼容性。
  • 函数自 WordPress 4.6.0 引入,相关钩子和函数需在兼容版本中使用。

📄 原文内容

Prints resource hints to browsers for pre-fetching, pre-rendering and pre-connecting to websites.

Description

Gives hints to browsers to prefetch specific pages or render them in the background, to perform DNS lookups or to begin the connection handshake (DNS, TCP, TLS) in the background.

These performance improving indicators work by using <link rel"…">.

Source

function wp_resource_hints() {
	$hints = array(
		'dns-prefetch' => wp_dependencies_unique_hosts(),
		'preconnect'   => array(),
		'prefetch'     => array(),
		'prerender'    => array(),
	);

	foreach ( $hints as $relation_type => $urls ) {
		$unique_urls = array();

		/**
		 * Filters domains and URLs for resource hints of the given relation type.
		 *
		 * @since 4.6.0
		 * @since 4.7.0 The `$urls` parameter accepts arrays of specific HTML attributes
		 *              as its child elements.
		 *
		 * @param array  $urls {
		 *     Array of resources and their attributes, or URLs to print for resource hints.
		 *
		 *     @type array|string ...$0 {
		 *         Array of resource attributes, or a URL string.
		 *
		 *         @type string $href        URL to include in resource hints. Required.
		 *         @type string $as          How the browser should treat the resource
		 *                                   (`script`, `style`, `image`, `document`, etc).
		 *         @type string $crossorigin Indicates the CORS policy of the specified resource.
		 *         @type float  $pr          Expected probability that the resource hint will be used.
		 *         @type string $type        Type of the resource (`text/html`, `text/css`, etc).
		 *     }
		 * }
		 * @param string $relation_type The relation type the URLs are printed for. One of
		 *                              'dns-prefetch', 'preconnect', 'prefetch', or 'prerender'.
		 */
		$urls = apply_filters( 'wp_resource_hints', $urls, $relation_type );

		foreach ( $urls as $key => $url ) {
			$atts = array();

			if ( is_array( $url ) ) {
				if ( isset( $url['href'] ) ) {
					$atts = $url;
					$url  = $url['href'];
				} else {
					continue;
				}
			}

			$url = esc_url( $url, array( 'http', 'https' ) );

			if ( ! $url ) {
				continue;
			}

			if ( isset( $unique_urls[ $url ] ) ) {
				continue;
			}

			if ( in_array( $relation_type, array( 'preconnect', 'dns-prefetch' ), true ) ) {
				$parsed = wp_parse_url( $url );

				if ( empty( $parsed['host'] ) ) {
					continue;
				}

				if ( 'preconnect' === $relation_type && ! empty( $parsed['scheme'] ) ) {
					$url = $parsed['scheme'] . '://' . $parsed['host'];
				} else {
					// Use protocol-relative URLs for dns-prefetch or if scheme is missing.
					$url = '//' . $parsed['host'];
				}
			}

			$atts['rel']  = $relation_type;
			$atts['href'] = $url;

			$unique_urls[ $url ] = $atts;
		}

		foreach ( $unique_urls as $atts ) {
			$html = '';

			foreach ( $atts as $attr => $value ) {
				if ( ! is_scalar( $value )
					|| ( ! in_array( $attr, array( 'as', 'crossorigin', 'href', 'pr', 'rel', 'type' ), true ) && ! is_numeric( $attr ) )
				) {

					continue;
				}

				$value = ( 'href' === $attr ) ? esc_url( $value ) : esc_attr( $value );

				if ( ! is_string( $attr ) ) {
					$html .= " $value";
				} else {
					$html .= " $attr='$value'";
				}
			}

			$html = trim( $html );

			echo "<link $html />n";
		}
	}
}

Hooks

apply_filters( ‘wp_resource_hints’, array $urls, string $relation_type )

Filters domains and URLs for resource hints of the given relation type.

Changelog

Version Description
4.6.0 Introduced.

User Contributed Notes

  1. Skip to note 3 content

    Sometimes, you may see this, removing the entire action in order to remove the reference to w.org:

    remove_action( 'wp_head', 'wp_resource_hints', 2 ); // removes dns-prefetch for w.org

    However, that eliminates the benefit of having dns-prefetch automatically added for external scripts.

    An alternative is just to remove the hard-coded reference, and keep dns-prefetch for performance gains:

    add_filter( 'wp_resource_hints', function( $urls ) {
    
        foreach ($urls as $key => $url) {
            // Remove dns-prefetch for w.org (we really don't need it)
            // See <a href="https://core.trac.wordpress.org/ticket/40426" rel="nofollow ugc">https://core.trac.wordpress.org/ticket/40426</a> for details 
            if ( 'https://s.w.org/images/core/emoji/13.0.0/svg/' === $url ) {
                unset( $urls[ $key ] );
            }
        }
    
        return $urls;
    } );

  2. Skip to note 4 content

    The newer way to remove (or alter) the DNS prefetch for s.w.org is to use the emoji_svg_url filter introduced in 4.6.0.

    // Remove WP Emoji DNS prefetch from document head
    add_filter( 'emoji_svg_url', '__return_false' );

    See https://core.trac.wordpress.org/attachment/ticket/40426/40426.diff