Make WordPress Core

Changeset 53846


Ignore:
Timestamp:
08/05/2022 06:24:42 PM (22 months ago)
Author:
adamsilverstein
Message:

Script loader: enable resource preloading with rel='preload'.

Add a wp_preload_resources filter that developers can use to add resource preloading.

Preloading helps the browser discover and prioritize important resources earlier during the page load. This ensures that they are available earlier and are less likely to block the page's render.

Props nico23, swissspidy, igrigorik, westonruter, azaozz, furi3r, aristath, spacedmonkey, peterwilsoncc, mihai2u, gziolo. 
Fixes #42438.

Location:
trunk
Files:
1 added
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/default-filters.php

    r53455 r53846  
    325325add_action( 'wp_head', 'wp_enqueue_scripts', 1 );
    326326add_action( 'wp_head', 'wp_resource_hints', 2 );
     327add_action( 'wp_head', 'wp_preload_resources', 1 );
    327328add_action( 'wp_head', 'feed_links', 2 );
    328329add_action( 'wp_head', 'feed_links_extra', 3 );
  • trunk/src/wp-includes/general-template.php

    r53740 r53846  
    34253425
    34263426/**
     3427 * Prints resource preloads directives to browsers.
     3428 *
     3429 * Gives directive to browsers to preload specific resources that website will
     3430 * need very soon, this ensures that they are available earlier and are less
     3431 * likely to block the page's render. Preload directives should not be used for
     3432 * non-render-blocking elements, as then they would compete with the
     3433 * render-blocking ones, slowing down the render.
     3434 *
     3435 * These performance improving indicators work by using `<link rel="preload">`.
     3436 *
     3437 * @link https://developer.mozilla.org/en-US/docs/Web/HTML/Link_types/preload
     3438 * @link https://web.dev/preload-responsive-images/
     3439 *
     3440 * @since 6.1.0
     3441 */
     3442function wp_preload_resources() {
     3443    /**
     3444     * Filters domains and URLs for resource preloads.
     3445     *
     3446     * @since 6.1.0
     3447     *
     3448     * @param array  $preload_resources {
     3449     *     Array of resources and their attributes, or URLs to print for resource preloads.
     3450     *
     3451     *     @type array ...$0 {
     3452     *         Array of resource attributes.
     3453     *
     3454     *         @type string $href        URL to include in resource preloads. Required.
     3455     *         @type string $as          How the browser should treat the resource
     3456     *                                   (`script`, `style`, `image`, `document`, etc).
     3457     *         @type string $crossorigin Indicates the CORS policy of the specified resource.
     3458     *         @type string $type        Type of the resource (`text/html`, `text/css`, etc).
     3459     *         @type string $media       Accepts media types or media queries. Allows responsive preloading.
     3460     *         @type string $imagesizes  Responsive source size to the source Set.
     3461     *         @type string $imagesrcset Responsive image sources to the source set.
     3462     *     }
     3463     * }
     3464     */
     3465    $preload_resources = apply_filters( 'wp_preload_resources', array() );
     3466
     3467    if ( ! is_array( $preload_resources ) ) {
     3468        return;
     3469    }
     3470
     3471    $unique_resources = array();
     3472
     3473    // Parse the complete resource list and extract unique resources.
     3474    foreach ( $preload_resources as $resource ) {
     3475        if ( ! is_array( $resource ) ) {
     3476            continue;
     3477        }
     3478
     3479        $attributes = $resource;
     3480        if ( isset( $resource['href'] ) ) {
     3481            $href = $resource['href'];
     3482            if ( isset( $unique_resources[ $href ] ) ) {
     3483                continue;
     3484            }
     3485            $unique_resources[ $href ] = $attributes;
     3486            // Media can use imagesrcset and not href.
     3487        } elseif ( ( 'image' === $resource['as'] ) &&
     3488            ( isset( $resource['imagesrcset'] ) || isset( $resource['imagesizes'] ) )
     3489        ) {
     3490            if ( isset( $unique_resources[ $resource['imagesrcset'] ] ) ) {
     3491                continue;
     3492            }
     3493            $unique_resources[ $resource['imagesrcset'] ] = $attributes;
     3494        } else {
     3495            continue;
     3496        }
     3497    }
     3498
     3499    // Build and output the HTML for each unique resource.
     3500    foreach ( $unique_resources as $unique_resource ) {
     3501        $html = '';
     3502
     3503        foreach ( $unique_resource as $resource_key => $resource_value ) {
     3504            if ( ! is_scalar( $resource_value ) ) {
     3505                continue;
     3506            }
     3507
     3508            // Ignore non-supported attributes.
     3509            $non_supported_attributes = array( 'as', 'crossorigin', 'href', 'imagesrcset', 'imagesizes', 'type', 'media' );
     3510            if ( ! in_array( $resource_key, $non_supported_attributes, true ) && ! is_numeric( $resource_key ) ) {
     3511                continue;
     3512            }
     3513
     3514            // imagesrcset only usable when preloading image, ignore otherwise.
     3515            if ( ( 'imagesrcset' === $resource_key ) && ( ! isset( $unique_resource['as'] ) || ( 'image' !== $unique_resource['as'] ) ) ) {
     3516                continue;
     3517            }
     3518
     3519            // imagesizes only usable when preloading image and imagesrcset present, ignore otherwise.
     3520            if ( ( 'imagesizes' === $resource_key ) &&
     3521                ( ! isset( $unique_resource['as'] ) || ( 'image' !== $unique_resource['as'] ) || ! isset( $unique_resource['imagesrcset'] ) )
     3522            ) {
     3523                continue;
     3524            }
     3525
     3526            $resource_value = ( 'href' === $resource_key ) ? esc_url( $resource_value, array( 'http', 'https' ) ) : esc_attr( $resource_value );
     3527
     3528            if ( ! is_string( $resource_key ) ) {
     3529                $html .= " $resource_value";
     3530            } else {
     3531                $html .= " $resource_key='$resource_value'";
     3532            }
     3533        }
     3534        $html = trim( $html );
     3535
     3536        printf( "<link rel='preload' %s />\n", $html );
     3537    }
     3538}
     3539
     3540/**
    34273541 * Retrieves a list of unique hosts of all enqueued scripts and styles.
    34283542 *
Note: See TracChangeset for help on using the changeset viewer.