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/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.