函数文档

wp_get_speculation_rules()

💡 云策文档标注

概述

wp_get_speculation_rules() 函数基于配置返回完整的推测规则数据,用于控制 WordPress 前端页面的预取或预渲染行为。它通过 WP_Speculation_Rules 对象管理规则,并支持通过过滤器和动作钩子进行自定义。

关键要点

  • 函数返回 WP_Speculation_Rules 对象或 null(如果推测加载在当前上下文中被禁用)。
  • 默认排除特定路径(如 /wp-admin/*),并支持通过 'wp_speculation_rules_href_exclude_paths' 过滤器添加自定义排除路径。
  • 使用 'wp_load_speculation_rules' 动作钩子可以修改或添加额外的推测规则。
  • 规则条件包括 href_matches 和 selector_matches,用于匹配 URL 和 CSS 选择器。
  • 函数内部处理路径前缀、重复项和顺序,确保规则列表有效。

代码示例

function wp_get_speculation_rules(): ?WP_Speculation_Rules {
    $configuration = wp_get_speculation_rules_configuration();
    if ( null === $configuration ) {
        return null;
    }

    $mode      = $configuration['mode'];
    $eagerness = $configuration['eagerness'];

    $prefixer = new WP_URL_Pattern_Prefixer();

    $base_href_exclude_paths = array(
        $prefixer->prefix_path_pattern( '/wp-*.php', 'site' ),
        $prefixer->prefix_path_pattern( '/wp-admin/*', 'site' ),
        $prefixer->prefix_path_pattern( '/*', 'uploads' ),
        $prefixer->prefix_path_pattern( '/*', 'content' ),
        $prefixer->prefix_path_pattern( '/*', 'plugins' ),
        $prefixer->prefix_path_pattern( '/*', 'template' ),
        $prefixer->prefix_path_pattern( '/*', 'stylesheet' ),
    );

    if ( get_option( 'permalink_structure' ) ) {
        $base_href_exclude_paths[] = $prefixer->prefix_path_pattern( '/*?(.+)', 'home' );
    } else {
        $base_href_exclude_paths[] = $prefixer->prefix_path_pattern( '/*?*(^|&)*nonce*=*', 'home' );
    }

    $href_exclude_paths = (array) apply_filters( 'wp_speculation_rules_href_exclude_paths', array(), $mode );

    $href_exclude_paths = array_values(
        array_unique(
            array_merge(
                $base_href_exclude_paths,
                array_map(
                    static function ( string $href_exclude_path ) use ( $prefixer ): string {
                        return $prefixer->prefix_path_pattern( $href_exclude_path );
                    },
                    $href_exclude_paths
                )
            )
        )
    );

    $speculation_rules = new WP_Speculation_Rules();

    $main_rule_conditions = array(
        array(
            'href_matches' => $prefixer->prefix_path_pattern( '/*' ),
        ),
        array(
            'not' => array(
                'href_matches' => $href_exclude_paths,
            ),
        ),
        array(
            'not' => array(
                'selector_matches' => 'a[rel~="nofollow"]',
            ),
        ),
        array(
            'not' => array(
                'selector_matches' => ".no-{$mode}, .no-{$mode} a",
            ),
        ),
    );

    if ( 'prerender' === $mode ) {
        $main_rule_conditions[] = array(
            'not' => array(
                'selector_matches' => '.no-prefetch, .no-prefetch a',
            ),
        );
    }

    $speculation_rules->add_rule(
        $mode,
        'main',
        array(
            'source'    => 'document',
            'where'     => array(
                'and' => $main_rule_conditions,
            ),
            'eagerness' => $eagerness,
        )
    );

    do_action( 'wp_load_speculation_rules', $speculation_rules );

    return $speculation_rules;
}

注意事项

  • 路径排除规则基于 WordPress 根目录,使用斜杠开头,支持通配符 *。
  • 某些核心路径(如 /wp-login.php)始终被排除,无法通过过滤器修改。
  • 在 'prerender' 模式下,会自动排除 'prefetch' 的退出选择器。
  • 函数自 WordPress 6.8.0 版本引入。

📄 原文内容

Returns the full speculation rules data based on the configuration.

Description

Plugins with features that rely on frontend URLs to exclude from prefetching or prerendering should use the ‘wp_speculation_rules_href_exclude_paths’ filter to ensure those URL patterns are excluded.

Additional speculation rules other than the default rule from WordPress Core can be provided by using the ‘wp_load_speculation_rules’ action and amending the passed WP_Speculation_Rules object.

Return

WP_Speculation_Rules|null Object representing the speculation rules to use, or null if speculative loading is disabled in the current context.

Source

function wp_get_speculation_rules(): ?WP_Speculation_Rules {
	$configuration = wp_get_speculation_rules_configuration();
	if ( null === $configuration ) {
		return null;
	}

	$mode      = $configuration['mode'];
	$eagerness = $configuration['eagerness'];

	$prefixer = new WP_URL_Pattern_Prefixer();

	$base_href_exclude_paths = array(
		$prefixer->prefix_path_pattern( '/wp-*.php', 'site' ),
		$prefixer->prefix_path_pattern( '/wp-admin/*', 'site' ),
		$prefixer->prefix_path_pattern( '/*', 'uploads' ),
		$prefixer->prefix_path_pattern( '/*', 'content' ),
		$prefixer->prefix_path_pattern( '/*', 'plugins' ),
		$prefixer->prefix_path_pattern( '/*', 'template' ),
		$prefixer->prefix_path_pattern( '/*', 'stylesheet' ),
	);

	/*
	 * If pretty permalinks are enabled, exclude any URLs with query parameters.
	 * Otherwise, exclude specifically the URLs with a `_wpnonce` query parameter or any other query parameter
	 * containing the word `nonce`.
	 */
	if ( get_option( 'permalink_structure' ) ) {
		$base_href_exclude_paths[] = $prefixer->prefix_path_pattern( '/*\?(.+)', 'home' );
	} else {
		$base_href_exclude_paths[] = $prefixer->prefix_path_pattern( '/*\?*(^|&)*nonce*=*', 'home' );
	}

	/**
	 * Filters the paths for which speculative loading should be disabled.
	 *
	 * All paths should start in a forward slash, relative to the root document. The `*` can be used as a wildcard.
	 * If the WordPress site is in a subdirectory, the exclude paths will automatically be prefixed as necessary.
	 *
	 * Note that WordPress always excludes certain path patterns such as `/wp-login.php` and `/wp-admin/*`, and those
	 * cannot be modified using the filter.
	 *
	 * @since 6.8.0
	 *
	 * @param string[] $href_exclude_paths Additional path patterns to disable speculative loading for.
	 * @param string   $mode               Mode used to apply speculative loading. Either 'prefetch' or 'prerender'.
	 */
	$href_exclude_paths = (array) apply_filters( 'wp_speculation_rules_href_exclude_paths', array(), $mode );

	// Ensure that:
	// 1. There are no duplicates.
	// 2. The base paths cannot be removed.
	// 3. The array has sequential keys (i.e. array_is_list()).
	$href_exclude_paths = array_values(
		array_unique(
			array_merge(
				$base_href_exclude_paths,
				array_map(
					static function ( string $href_exclude_path ) use ( $prefixer ): string {
						return $prefixer->prefix_path_pattern( $href_exclude_path );
					},
					$href_exclude_paths
				)
			)
		)
	);

	$speculation_rules = new WP_Speculation_Rules();

	$main_rule_conditions = array(
		// Include any URLs within the same site.
		array(
			'href_matches' => $prefixer->prefix_path_pattern( '/*' ),
		),
		// Except for excluded paths.
		array(
			'not' => array(
				'href_matches' => $href_exclude_paths,
			),
		),
		// Also exclude rel=nofollow links, as certain plugins use that on their links that perform an action.
		array(
			'not' => array(
				'selector_matches' => 'a[rel~="nofollow"]',
			),
		),
		// Also exclude links that are explicitly marked to opt out, either directly or via a parent element.
		array(
			'not' => array(
				'selector_matches' => ".no-{$mode}, .no-{$mode} a",
			),
		),
	);

	// If using 'prerender', also exclude links that opt out of 'prefetch' because it's part of 'prerender'.
	if ( 'prerender' === $mode ) {
		$main_rule_conditions[] = array(
			'not' => array(
				'selector_matches' => '.no-prefetch, .no-prefetch a',
			),
		);
	}

	$speculation_rules->add_rule(
		$mode,
		'main',
		array(
			'source'    => 'document',
			'where'     => array(
				'and' => $main_rule_conditions,
			),
			'eagerness' => $eagerness,
		)
	);

	/**
	 * Fires when speculation rules data is loaded, allowing to amend the rules.
	 *
	 * @since 6.8.0
	 *
	 * @param WP_Speculation_Rules $speculation_rules Object representing the speculation rules to use.
	 */
	do_action( 'wp_load_speculation_rules', $speculation_rules );

	return $speculation_rules;
}

Hooks

do_action( ‘wp_load_speculation_rules’, WP_Speculation_Rules $speculation_rules )

Fires when speculation rules data is loaded, allowing to amend the rules.

apply_filters( ‘wp_speculation_rules_href_exclude_paths’, string[] $href_exclude_paths, string $mode )

Filters the paths for which speculative loading should be disabled.

Changelog

Version Description
6.8.0 Introduced.