wp_resource_hints()WP 4.6.0

Выводит на экран <link> теги для dns-prefetch, preconnect, prefetch, prerender.

Эти теги дают браузерам подсказки для предварительных действий. Подробнее читайте здесь.

Функция не предназначена для прямого использования - она повешена на хук wp_head в ядре WP, см. файл wp-includes/default-filters.php:

add_action( 'wp_head', 'wp_resource_hints', 2 );

WP с помощью этой функции, автоматически добавляет dns-prefetch <link> для всех внешних подключаемых скриптов.

В сети можно встретить такую рекомендацию, чтобы отключить префетч для emoji:

// плохая идея:
remove_action( 'wp_head', 'wp_resource_hints', 2 );

НИКОГДА так не делайте!

Как правильно смотрите ниже в примере.

Работает на основе: wp_dependencies_unique_hosts()
1 раз — 0.000474 сек (быстро) | 50000 раз — 7.01 сек (быстро) | PHP 7.4.25, WP 6.0
Хуки из функции

Возвращает

null. Ничего.

Использование

wp_resource_hints();

Примеры

0

#1 Как правильно отключить DNS prefetch для s.w.org (emoji)

С версии 4.6.0 появился специальный хук, который позволяет отключить префетч для s.w.org (emoji):

// Удаление DNS prefetch для WP Emoji из шапки
add_filter( 'emoji_svg_url', '__return_false' );
0

#2 Добавим prefetch инструкции для кастомных URL (доменов)

Допустим нам нужно форсировано добавить инструкции для браузера для определенных УРЛ или доменов - используем хук wp_resource_hints:

add_filter( 'wp_resource_hints', 'wp_kama_resource_hints_filter', 10, 2 );

/**
 * Function for `wp_resource_hints` filter-hook.
 *
 * @param array  $urls          Array of resources and their attributes, or URLs to print for resource hints.
 * @param string $relation_type The relation type the URLs are printed for, e.g. 'preconnect' or 'prerender'.
 *
 * @return array
 */
function wp_kama_resource_hints_filter( $urls, $relation_type ){

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

	if( 'preconnect' === $relation_type ){
		$urls[] = 'https://preconnect.com/some';
	}

	if( 'prefetch' === $relation_type ){
		$urls[] = 'https://prefetch.com/some';
		$urls[] = '//prefetch-no-proto.com/some';
		$urls[] = [
			'href'        => 'https://prerender-array.com/some.css',
			'as'          => 'style',
			'crossorigin' => 'use-credentials',
			'pr'          => 12.5,
			'type'        => 'text/css',
		];
	}

	if( 'prerender' === $relation_type ){
		$urls[] = 'https://prerender.com/some';
	}

	return $urls;
}

Получим в HEAD части HTML:

<link rel='dns-prefetch' href='//dnsprefetch.com' />

<link rel='preconnect' href='https://preconnect.com' />

<link rel='prefetch' href='https://prefetch.com/some' />
<link rel='prefetch' href='//prefetch-no-proto.com/some' />
<link href='https://prerender-array.com/some.css' as='style' crossorigin='use-credentials' pr='12.5' type='text/css' rel='prefetch' />

<link rel='prerender' href='https://prerender.com/some' />

Список изменений

С версии 4.6.0 Введена.

Код wp_resource_hints() WP 6.0

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

	/*
	 * Add DNS prefetch for the Emoji CDN.
	 * The path is removed in the foreach loop below.
	 */
	/** This filter is documented in wp-includes/formatting.php */
	$hints['dns-prefetch'][] = apply_filters( 'emoji_svg_url', 'https://s.w.org/images/core/emoji/13.0.0/svg/' );

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

		/**
		 * Filters domains and URLs for resource hints of 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,
		 *                              e.g. 'preconnect' 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";
		}
	}
}