Make WordPress Core


Ignore:
Timestamp:
09/03/2025 10:15:31 PM (5 months ago)
Author:
westonruter
Message:

Script Loader: Introduce fetchpriority for Scripts and Script Modules.

  • Allow scripts and script modules to be registered with a fetchpriority of auto (default), high, low:
    • When registering a script, add a fetchpriority arg to go alongside the strategy arg which was added for loading scripts with the defer and async loading strategies. See #12009.
    • For script modules, introduce an $args array parameter with a fetchpriority key to the wp_register_script_module(), and wp_enqueue_script_module() functions (and their respective underlying WP_Script_Modules::register() and WP_Script_Modules::enqueue() methods). This $args parameter corresponds with the same parameter used when registering non-module scripts.
    • Also for script modules, introduce WP_Script_Modules::set_fetchpriority() to override the fetchpriority for what was previously registered.
    • Emit a _doing_it_wrong() warning when an invalid fetchpriority value is used, and when fetchpriority is added to a script alias.
    • Include fetchpriority as an attribute on printed SCRIPT tags as well as on preload LINK tags for static script module dependencies.
  • Use a fetchpriority of low by default for:
    • Script modules used with the Interactivity API. For overriding this default in blocks, see Gutenberg#71366.
    • The comment-reply script.
  • Improve type checks and type hints.

Developed in GitHub PR, with companion for Gutenberg.

Props westonruter, jonsurrell, swissspidy, luisherranz, kraftbj, audrasjb, dennysdionigi.
Fixes #61734.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/class-wp-script-modules.php

    r60681 r60704  
    4747     *
    4848     * @since 6.5.0
     49     * @since 6.9.0 Added the $args parameter.
    4950     *
    5051     * @param string            $id       The identifier of the script module. Should be unique. It will be used in the
     
    7273     *                                    is set to false, the version number is the currently installed WordPress version.
    7374     *                                    If $version is set to null, no version is added.
    74      */
    75     public function register( string $id, string $src, array $deps = array(), $version = false ) {
     75     * @param array             $args     {
     76     *     Optional. An array of additional args. Default empty array.
     77     *
     78     *     @type 'auto'|'low'|'high' $fetchpriority Fetch priority. Default 'auto'. Optional.
     79     * }
     80     */
     81    public function register( string $id, string $src, array $deps = array(), $version = false, array $args = array() ) {
    7682        if ( ! isset( $this->registered[ $id ] ) ) {
    7783            $dependencies = array();
    7884            foreach ( $deps as $dependency ) {
    7985                if ( is_array( $dependency ) ) {
    80                     if ( ! isset( $dependency['id'] ) ) {
     86                    if ( ! isset( $dependency['id'] ) || ! is_string( $dependency['id'] ) ) {
    8187                        _doing_it_wrong( __METHOD__, __( 'Missing required id key in entry among dependencies array.' ), '6.5.0' );
    8288                        continue;
     
    96102            }
    97103
     104            $fetchpriority = 'auto';
     105            if ( isset( $args['fetchpriority'] ) ) {
     106                if ( $this->is_valid_fetchpriority( $args['fetchpriority'] ) ) {
     107                    $fetchpriority = $args['fetchpriority'];
     108                } else {
     109                    _doing_it_wrong(
     110                        __METHOD__,
     111                        sprintf(
     112                            /* translators: 1: $fetchpriority, 2: $id */
     113                            __( 'Invalid fetchpriority `%1$s` defined for `%2$s` during script registration.' ),
     114                            is_string( $args['fetchpriority'] ) ? $args['fetchpriority'] : gettype( $args['fetchpriority'] ),
     115                            $id
     116                        ),
     117                        '6.9.0'
     118                    );
     119                }
     120            }
     121
    98122            $this->registered[ $id ] = array(
    99                 'src'          => $src,
    100                 'version'      => $version,
    101                 'enqueue'      => isset( $this->enqueued_before_registered[ $id ] ),
    102                 'dependencies' => $dependencies,
     123                'src'           => $src,
     124                'version'       => $version,
     125                'enqueue'       => isset( $this->enqueued_before_registered[ $id ] ),
     126                'dependencies'  => $dependencies,
     127                'fetchpriority' => $fetchpriority,
    103128            );
    104129        }
     130    }
     131
     132    /**
     133     * Checks if the provided fetchpriority is valid.
     134     *
     135     * @since 6.9.0
     136     *
     137     * @param string|mixed $priority Fetch priority.
     138     * @return bool Whether valid fetchpriority.
     139     */
     140    private function is_valid_fetchpriority( $priority ): bool {
     141        return in_array( $priority, array( 'auto', 'low', 'high' ), true );
     142    }
     143
     144    /**
     145     * Sets the fetch priority for a script module.
     146     *
     147     * @since 6.9.0
     148     *
     149     * @param string              $id       Script module identifier.
     150     * @param 'auto'|'low'|'high' $priority Fetch priority for the script module.
     151     * @return bool Whether setting the fetchpriority was successful.
     152     */
     153    public function set_fetchpriority( string $id, string $priority ): bool {
     154        if ( ! isset( $this->registered[ $id ] ) ) {
     155            return false;
     156        }
     157
     158        if ( '' === $priority ) {
     159            $priority = 'auto';
     160        }
     161
     162        if ( ! $this->is_valid_fetchpriority( $priority ) ) {
     163            _doing_it_wrong(
     164                __METHOD__,
     165                /* translators: %s: Invalid fetchpriority. */
     166                sprintf( __( 'Invalid fetchpriority: %s' ), $priority ),
     167                '6.9.0'
     168            );
     169            return false;
     170        }
     171
     172        $this->registered[ $id ]['fetchpriority'] = $priority;
     173        return true;
    105174    }
    106175
     
    112181     *
    113182     * @since 6.5.0
     183     * @since 6.9.0 Added the $args parameter.
    114184     *
    115185     * @param string            $id       The identifier of the script module. Should be unique. It will be used in the
     
    137207     *                                    is set to false, the version number is the currently installed WordPress version.
    138208     *                                    If $version is set to null, no version is added.
    139      */
    140     public function enqueue( string $id, string $src = '', array $deps = array(), $version = false ) {
     209     * @param array             $args     {
     210     *     Optional. An array of additional args. Default empty array.
     211     *
     212     *     @type 'auto'|'low'|'high' $fetchpriority Fetch priority. Default 'auto'. Optional.
     213     * }
     214     */
     215    public function enqueue( string $id, string $src = '', array $deps = array(), $version = false, array $args = array() ) {
    141216        if ( isset( $this->registered[ $id ] ) ) {
    142217            $this->registered[ $id ]['enqueue'] = true;
    143218        } elseif ( $src ) {
    144             $this->register( $id, $src, $deps, $version );
     219            $this->register( $id, $src, $deps, $version, $args );
    145220            $this->registered[ $id ]['enqueue'] = true;
    146221        } else {
     
    209284    public function print_enqueued_script_modules() {
    210285        foreach ( $this->get_marked_for_enqueue() as $id => $script_module ) {
    211             wp_print_script_tag(
    212                 array(
    213                     'type' => 'module',
    214                     'src'  => $this->get_src( $id ),
    215                     'id'   => $id . '-js-module',
    216                 )
     286            $args = array(
     287                'type' => 'module',
     288                'src'  => $this->get_src( $id ),
     289                'id'   => $id . '-js-module',
    217290            );
     291            if ( 'auto' !== $script_module['fetchpriority'] ) {
     292                $args['fetchpriority'] = $script_module['fetchpriority'];
     293            }
     294            wp_print_script_tag( $args );
    218295        }
    219296    }
     
    232309            if ( true !== $script_module['enqueue'] ) {
    233310                echo sprintf(
    234                     '<link rel="modulepreload" href="%s" id="%s">',
     311                    '<link rel="modulepreload" href="%s" id="%s"%s>',
    235312                    esc_url( $this->get_src( $id ) ),
    236                     esc_attr( $id . '-js-modulepreload' )
     313                    esc_attr( $id . '-js-modulepreload' ),
     314                    'auto' !== $script_module['fetchpriority'] ? sprintf( ' fetchpriority="%s"', esc_attr( $script_module['fetchpriority'] ) ) : ''
    237315                );
    238316            }
     
    279357     * @since 6.5.0
    280358     *
    281      * @return array[] Script modules marked for enqueue, keyed by script module identifier.
     359     * @return array<string, array> Script modules marked for enqueue, keyed by script module identifier.
    282360     */
    283361    private function get_marked_for_enqueue(): array {
Note: See TracChangeset for help on using the changeset viewer.