I have this function in my functions.php file:

function dns_prefetch_to_preconnect( $urls, $relation_type ) {
    if ( 'dns-prefetch' === $relation_type ) {
        $urls = [];
    }

    if ( 'preconnect' === $relation_type ) {
        $urls = wp_dependencies_unique_hosts();
    }

    return $urls;
}
add_filter( 'wp_resource_hints', 'dns_prefetch_to_preconnect', 0, 2 );

It takes the URLs defined in wp_dependencies_unique_hosts() – which WordPress by default assigns to the dns-prefetch link tag – and reassigns them to the preconnect link tag. The function was provided to me here:

Change dns-prefetch to preconnect for external enqueued resources

However, this function isn't working entirely correctly. It adds the preconnect URLs using http instead of https.

Example: when I'm not using the above function, WordPress adds this link to my header:

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

And when I enable the above function, it replaces that link with this link:

<link rel='preconnect' href='http://fonts.googleapis.com' />

The problem, of course, is that it should be https, not http.

Can someone help me modify my function so that it gives me https links?

有帮助吗?

解决方案 2

I've finally got it working now, as follows:

First I found the original wp_dependencies_unique_hosts() function from the WordPress code (it's in a file called general-template.php), and I made a copy of it, but giving it a new name: wp_dependencies_unique_urls().

I observed that this function is using wp_parse_url() to grab just the host part of each URL from the list of scripts and styles. In other words, it's dropping the scheme, which is the reason for the problem I'm having.

So I modified the function to include the scheme - here it is in its entirety:

function wp_dependencies_unique_urls() {
    global $wp_scripts, $wp_styles;

    $unique_urls = array();

    foreach ( array( $wp_scripts, $wp_styles ) as $dependencies ) {
        if ( $dependencies instanceof WP_Dependencies && ! empty( $dependencies->queue ) ) {
            foreach ( $dependencies->queue as $handle ) {
                if ( ! isset( $dependencies->registered[ $handle ] ) ) {
                    continue;
                }

                $dependency = $dependencies->registered[ $handle ];
                $parsed     = wp_parse_url( $dependency->src );

                if ( ! empty( $parsed['host'] ) && ! in_array( $parsed['host'], $unique_urls ) && $parsed['host'] !== $_SERVER['SERVER_NAME'] ) {
                    $unique_urls[] = $parsed['scheme'] . '://' . $parsed['host'];
                }
            }
        }
    }

    return $unique_urls;
}

As you can see, the main thing I've changed is this:

$unique_urls[] = $parsed['scheme'] . '://' . $parsed['host'];

I hope this is the best way to add the scheme to the beginning of each URL.

Next, I modified my original function (from my original question above) so it calls this new function I've created:

function dns_prefetch_to_preconnect( $urls, $relation_type ) {

    if ( 'dns-prefetch' === $relation_type ) {
        $urls = [];
    }

    if ( 'preconnect' === $relation_type ) {
        $urls = wp_dependencies_unique_urls();
    }

    return $urls;
}
add_filter( 'wp_resource_hints', 'dns_prefetch_to_preconnect', 0, 2 );

Et voila, it works! I now have valid 'preconnect' links in my page headers, which use the same scheme as the original enqueued scripts and styles - either http or https!

And if I want to, I can combine my two functions into one big function for simplicity:

function dns_prefetch_to_preconnect( $urls, $relation_type ) {
    global $wp_scripts, $wp_styles;

    $unique_urls = array();

    foreach ( array( $wp_scripts, $wp_styles ) as $dependencies ) {
        if ( $dependencies instanceof WP_Dependencies && ! empty( $dependencies->queue ) ) {
            foreach ( $dependencies->queue as $handle ) {
                if ( ! isset( $dependencies->registered[ $handle ] ) ) {
                    continue;
                }

                $dependency = $dependencies->registered[ $handle ];
                $parsed     = wp_parse_url( $dependency->src );

                if ( ! empty( $parsed['host'] ) && ! in_array( $parsed['host'], $unique_urls ) && $parsed['host'] !== $_SERVER['SERVER_NAME'] ) {
                    $unique_urls[] = $parsed['scheme'] . '://' . $parsed['host'];
                }
            }
        }
    }

    if ( 'dns-prefetch' === $relation_type ) {
        $urls = [];
    }

    if ( 'preconnect' === $relation_type ) {
        $urls = $unique_urls;
    }

    return $urls;
}
add_filter( 'wp_resource_hints', 'dns_prefetch_to_preconnect', 0, 2 );

其他提示

The problem is not that the function you're using adds http:, the problem is it adds no URL schema at all!

As a result, WP needs to add a URL schema to turn the host into a URL, and so it uses http://. It has no way of knowing what the original was, or if the host supports HTTPS, so http:// is the safe bet.

If however you passed the array with URL schema added, it would be passed through without issue.

Something like this may do the trick:

$hosts = wp_dependencies_unique_hosts();
$urls = array_map( function( $host ) {
    return set_url_scheme( $host, 'https' );
}, $hosts );

In the longrun though, it would be better to get the actual URLs and distill the host URL out of them, rather than relying on wp_dependencies_unique_hosts if you wanted to preserve the mixture of http and https

许可以下: CC-BY-SA归因
scroll top