Make WordPress Core


Ignore:
Timestamp:
09/03/2025 10:15:31 PM (12 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/tests/phpunit/tests/dependencies/scripts.php

    r60690 r60704  
    11281128         * Tests that dependents that are async but attached to a deferred main script, print with defer as opposed to async.
    11291129         *
     1130         * Also tests that fetchpriority attributes are added as expected.
     1131         *
    11301132         * @ticket 12009
     1133         * @ticket 61734
    11311134         *
    11321135         * @covers WP_Scripts::do_item
    11331136         * @covers WP_Scripts::get_eligible_loading_strategy
     1137         * @covers ::wp_register_script
    11341138         * @covers ::wp_enqueue_script
    11351139         */
    11361140        public function test_defer_with_async_dependent() {
    11371141                // case with one async dependent.
    1138                 wp_enqueue_script( 'main-script-d4', '/main-script-d4.js', array(), null, array( 'strategy' => 'defer' ) );
    1139                 wp_enqueue_script( 'dependent-script-d4-1', '/dependent-script-d4-1.js', array( 'main-script-d4' ), null, array( 'strategy' => 'defer' ) );
    1140                 wp_enqueue_script( 'dependent-script-d4-2', '/dependent-script-d4-2.js', array( 'dependent-script-d4-1' ), null, array( 'strategy' => 'async' ) );
    1141                 wp_enqueue_script( 'dependent-script-d4-3', '/dependent-script-d4-3.js', array( 'dependent-script-d4-2' ), null, array( 'strategy' => 'defer' ) );
     1142                wp_register_script( 'main-script-d4', '/main-script-d4.js', array(), null, array( 'strategy' => 'defer' ) );
     1143                wp_enqueue_script(
     1144                        'dependent-script-d4-1',
     1145                        '/dependent-script-d4-1.js',
     1146                        array( 'main-script-d4' ),
     1147                        null,
     1148                        array(
     1149                                'strategy'      => 'defer',
     1150                                'fetchpriority' => 'auto',
     1151                        )
     1152                );
     1153                wp_enqueue_script(
     1154                        'dependent-script-d4-2',
     1155                        '/dependent-script-d4-2.js',
     1156                        array( 'dependent-script-d4-1' ),
     1157                        null,
     1158                        array(
     1159                                'strategy'      => 'async',
     1160                                'fetchpriority' => 'low',
     1161                        )
     1162                );
     1163                wp_enqueue_script(
     1164                        'dependent-script-d4-3',
     1165                        '/dependent-script-d4-3.js',
     1166                        array( 'dependent-script-d4-2' ),
     1167                        null,
     1168                        array(
     1169                                'strategy'      => 'defer',
     1170                                'fetchpriority' => 'high',
     1171                        )
     1172                );
    11421173                $output    = get_echo( 'wp_print_scripts' );
    11431174                $expected  = "<script type='text/javascript' src='/main-script-d4.js' id='main-script-d4-js' defer='defer' data-wp-strategy='defer'></script>\n";
    11441175                $expected .= "<script type='text/javascript' src='/dependent-script-d4-1.js' id='dependent-script-d4-1-js' defer='defer' data-wp-strategy='defer'></script>\n";
    1145                 $expected .= "<script type='text/javascript' src='/dependent-script-d4-2.js' id='dependent-script-d4-2-js' defer='defer' data-wp-strategy='async'></script>\n";
    1146                 $expected .= "<script type='text/javascript' src='/dependent-script-d4-3.js' id='dependent-script-d4-3-js' defer='defer' data-wp-strategy='defer'></script>\n";
     1176                $expected .= "<script type='text/javascript' src='/dependent-script-d4-2.js' id='dependent-script-d4-2-js' defer='defer' data-wp-strategy='async' fetchpriority='low'></script>\n";
     1177                $expected .= "<script type='text/javascript' src='/dependent-script-d4-3.js' id='dependent-script-d4-3-js' defer='defer' data-wp-strategy='defer' fetchpriority='high'></script>\n";
    11471178
    11481179                $this->assertEqualHTML( $expected, $output, '<body>', 'Scripts registered as defer but that have dependents that are async are expected to have said dependents deferred.' );
     1180        }
     1181
     1182        /**
     1183         * Data provider for test_fetchpriority_values.
     1184         *
     1185         * @return array<string, array{fetchpriority: string}>
     1186         */
     1187        public function data_provider_fetchpriority_values(): array {
     1188                return array(
     1189                        'auto' => array( 'fetchpriority' => 'auto' ),
     1190                        'low'  => array( 'fetchpriority' => 'low' ),
     1191                        'high' => array( 'fetchpriority' => 'high' ),
     1192                );
     1193        }
     1194
     1195        /**
     1196         * Tests that valid fetchpriority values are correctly added to script data.
     1197         *
     1198         * @ticket 61734
     1199         *
     1200         * @covers ::wp_register_script
     1201         * @covers WP_Scripts::add_data
     1202         * @covers ::wp_script_add_data
     1203         *
     1204         * @dataProvider data_provider_fetchpriority_values
     1205         *
     1206         * @param string $fetchpriority The fetchpriority value to test.
     1207         */
     1208        public function test_fetchpriority_values( string $fetchpriority ) {
     1209                wp_register_script( 'test-script', '/test-script.js', array(), null, array( 'fetchpriority' => $fetchpriority ) );
     1210                $this->assertArrayHasKey( 'fetchpriority', wp_scripts()->registered['test-script']->extra );
     1211                $this->assertSame( $fetchpriority, wp_scripts()->registered['test-script']->extra['fetchpriority'] );
     1212
     1213                wp_register_script( 'test-script-2', '/test-script-2.js' );
     1214                $this->assertTrue( wp_script_add_data( 'test-script-2', 'fetchpriority', $fetchpriority ) );
     1215                $this->assertArrayHasKey( 'fetchpriority', wp_scripts()->registered['test-script-2']->extra );
     1216                $this->assertSame( $fetchpriority, wp_scripts()->registered['test-script-2']->extra['fetchpriority'] );
     1217        }
     1218
     1219        /**
     1220         * Tests that an empty fetchpriority is treated the same as auto.
     1221         *
     1222         * @ticket 61734
     1223         *
     1224         * @covers ::wp_register_script
     1225         * @covers WP_Scripts::add_data
     1226         */
     1227        public function test_empty_fetchpriority_value() {
     1228                wp_register_script( 'unset', '/joke.js', array(), null, array( 'fetchpriority' => 'low' ) );
     1229                $this->assertSame( 'low', wp_scripts()->registered['unset']->extra['fetchpriority'] );
     1230                $this->assertTrue( wp_script_add_data( 'unset', 'fetchpriority', null ) );
     1231                $this->assertSame( 'auto', wp_scripts()->registered['unset']->extra['fetchpriority'] );
     1232        }
     1233
     1234        /**
     1235         * Tests that an invalid fetchpriority causes a _doing_it_wrong() warning.
     1236         *
     1237         * @ticket 61734
     1238         *
     1239         * @covers ::wp_register_script
     1240         * @covers WP_Scripts::add_data
     1241         *
     1242         * @expectedIncorrectUsage WP_Scripts::add_data
     1243         */
     1244        public function test_invalid_fetchpriority_value() {
     1245                wp_register_script( 'joke', '/joke.js', array(), null, array( 'fetchpriority' => 'silly' ) );
     1246                $this->assertArrayNotHasKey( 'fetchpriority', wp_scripts()->registered['joke']->extra );
     1247                $this->assertArrayHasKey( 'WP_Scripts::add_data', $this->caught_doing_it_wrong );
     1248                $this->assertStringContainsString( 'Invalid fetchpriority `silly`', $this->caught_doing_it_wrong['WP_Scripts::add_data'] );
     1249        }
     1250
     1251        /**
     1252         * Tests that an invalid fetchpriority causes a _doing_it_wrong() warning.
     1253         *
     1254         * @ticket 61734
     1255         *
     1256         * @covers ::wp_register_script
     1257         * @covers WP_Scripts::add_data
     1258         *
     1259         * @expectedIncorrectUsage WP_Scripts::add_data
     1260         */
     1261        public function test_invalid_fetchpriority_value_type() {
     1262                wp_register_script( 'bad', '/bad.js' );
     1263                $this->assertFalse( wp_script_add_data( 'bad', 'fetchpriority', array( 'THIS IS SO WRONG!!!' ) ) );
     1264                $this->assertArrayNotHasKey( 'fetchpriority', wp_scripts()->registered['bad']->extra );
     1265                $this->assertArrayHasKey( 'WP_Scripts::add_data', $this->caught_doing_it_wrong );
     1266                $this->assertStringContainsString( 'Invalid fetchpriority `array`', $this->caught_doing_it_wrong['WP_Scripts::add_data'] );
     1267        }
     1268
     1269        /**
     1270         * Tests that adding fetchpriority causes a _doing_it_wrong() warning on a script alias.
     1271         *
     1272         * @ticket 61734
     1273         *
     1274         * @covers ::wp_register_script
     1275         * @covers WP_Scripts::add_data
     1276         *
     1277         * @expectedIncorrectUsage WP_Scripts::add_data
     1278         */
     1279        public function test_invalid_fetchpriority_on_alias() {
     1280                wp_register_script( 'alias', false, array(), null, array( 'fetchpriority' => 'low' ) );
     1281                $this->assertArrayNotHasKey( 'fetchpriority', wp_scripts()->registered['alias']->extra );
    11491282        }
    11501283
Note: See TracChangeset for help on using the changeset viewer.