-
Notifications
You must be signed in to change notification settings - Fork 3.2k
Introduce fetchpriority for Scripts and Script Modules
#8815
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 12 commits
dbcd32c
5207c27
088366d
9eab85d
d9c4037
4f82a4f
f2cd9be
ff4fd36
9edbe4c
021fe74
34ef7fa
e54274a
cc1d909
4197eb2
74a49e1
75fb879
0e9994a
06e9cac
f91c61d
4596644
2172e9e
535669d
fe366e2
f704f5e
38150dc
f05ca72
607ce0c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -12,13 +12,22 @@ | |
| * Core class used to register script modules. | ||
| * | ||
| * @since 6.5.0 | ||
| * | ||
| * @phpstan-type ScriptModule array{ | ||
| * src: string, | ||
| * version: string|false|null, | ||
| * enqueue: bool, | ||
| * dependencies: array<array{ id: string, import: 'dynamic'|'static' }>, | ||
| * fetchpriority: 'auto'|'low'|'high', | ||
| * } | ||
|
||
| */ | ||
| class WP_Script_Modules { | ||
| /** | ||
| * Holds the registered script modules, keyed by script module identifier. | ||
| * | ||
| * @since 6.5.0 | ||
| * @var array[] | ||
| * @phpstan-var array<string, ScriptModule> | ||
| */ | ||
| private $registered = array(); | ||
|
|
||
|
|
@@ -46,6 +55,7 @@ class WP_Script_Modules { | |
| * identifier has already been registered. | ||
| * | ||
| * @since 6.5.0 | ||
| * @since n.e.x.t Added the $args parameter. | ||
| * | ||
| * @param string $id The identifier of the script module. Should be unique. It will be used in the | ||
| * final import map. | ||
|
|
@@ -71,13 +81,18 @@ class WP_Script_Modules { | |
| * It is added to the URL as a query string for cache busting purposes. If $version | ||
| * is set to false, the version number is the currently installed WordPress version. | ||
| * If $version is set to null, no version is added. | ||
| * @param array $args { | ||
| * Optional. An array of additional args. Default empty array. | ||
| * | ||
| * @type 'auto'|'low'|'high' $fetchpriority Fetch priority. Default 'auto'. Optional. | ||
sirreal marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| * } | ||
| */ | ||
| public function register( string $id, string $src, array $deps = array(), $version = false ) { | ||
| public function register( string $id, string $src, array $deps = array(), $version = false, array $args = array() ) { | ||
| if ( ! isset( $this->registered[ $id ] ) ) { | ||
| $dependencies = array(); | ||
| foreach ( $deps as $dependency ) { | ||
| if ( is_array( $dependency ) ) { | ||
| if ( ! isset( $dependency['id'] ) ) { | ||
| if ( ! isset( $dependency['id'] ) || ! is_string( $dependency['id'] ) ) { | ||
| _doing_it_wrong( __METHOD__, __( 'Missing required id key in entry among dependencies array.' ), '6.5.0' ); | ||
| continue; | ||
| } | ||
|
|
@@ -95,22 +110,76 @@ public function register( string $id, string $src, array $deps = array(), $versi | |
| } | ||
| } | ||
|
|
||
| $fetchpriority = 'auto'; | ||
| if ( isset( $args['fetchpriority'] ) ) { | ||
| if ( $this->is_valid_fetchpriority( $args['fetchpriority'] ) ) { | ||
| $fetchpriority = $args['fetchpriority']; | ||
| } else { | ||
| _doing_it_wrong( | ||
| __METHOD__, | ||
| /* translators: %s: Invalid fetchpriority. */ | ||
| sprintf( __( 'Invalid fetchpriority: %s' ), $args['fetchpriority'] ), | ||
| 'n.e.x.t' | ||
| ); | ||
| } | ||
| } | ||
|
|
||
| $this->registered[ $id ] = array( | ||
| 'src' => $src, | ||
| 'version' => $version, | ||
| 'enqueue' => isset( $this->enqueued_before_registered[ $id ] ), | ||
| 'dependencies' => $dependencies, | ||
| 'src' => $src, | ||
| 'version' => $version, | ||
| 'enqueue' => isset( $this->enqueued_before_registered[ $id ] ), | ||
| 'dependencies' => $dependencies, | ||
| 'fetchpriority' => $fetchpriority, | ||
| ); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Checks if the provided fetchpriority is valid. | ||
| * | ||
| * @since n.e.x.t | ||
| * | ||
| * @param mixed $priority Fetch priority. | ||
| * @return bool Whether valid fetchpriority. | ||
| */ | ||
| private function is_valid_fetchpriority( $priority ): bool { | ||
| return in_array( $priority, array( 'auto', 'low', 'high' ), true ); | ||
sirreal marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| /** | ||
| * Sets the fetch priority for a script module. | ||
| * | ||
| * @since n.e.x.t | ||
| * | ||
| * @param string $id Script module identifier. | ||
| * @param 'auto'|'low'|'high' $priority Fetch priority for the script module. | ||
| */ | ||
| public function set_fetchpriority( string $id, string $priority ) { | ||
| if ( ! isset( $this->registered[ $id ] ) ) { | ||
| return; | ||
| } | ||
|
|
||
| if ( ! $this->is_valid_fetchpriority( $priority ) ) { | ||
| _doing_it_wrong( | ||
| __METHOD__, | ||
| /* translators: %s: Invalid fetchpriority. */ | ||
| sprintf( __( 'Invalid fetchpriority: %s' ), $priority ), | ||
| 'n.e.x.t' | ||
| ); | ||
| return; | ||
| } | ||
|
|
||
| $this->registered[ $id ]['fetchpriority'] = $priority; | ||
| } | ||
|
|
||
| /** | ||
| * Marks the script module to be enqueued in the page. | ||
| * | ||
| * If a src is provided and the script module has not been registered yet, it | ||
| * will be registered. | ||
| * | ||
| * @since 6.5.0 | ||
| * @since n.e.x.t Added the $args parameter. | ||
| * | ||
| * @param string $id The identifier of the script module. Should be unique. It will be used in the | ||
| * final import map. | ||
|
|
@@ -136,12 +205,17 @@ public function register( string $id, string $src, array $deps = array(), $versi | |
| * It is added to the URL as a query string for cache busting purposes. If $version | ||
| * is set to false, the version number is the currently installed WordPress version. | ||
| * If $version is set to null, no version is added. | ||
| * @param array $args { | ||
westonruter marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| * Optional. An array of additional args. Default empty array. | ||
| * | ||
| * @type 'auto'|'low'|'high' $fetchpriority Fetch priority. Default 'auto'. Optional. | ||
| * } | ||
| */ | ||
| public function enqueue( string $id, string $src = '', array $deps = array(), $version = false ) { | ||
| public function enqueue( string $id, string $src = '', array $deps = array(), $version = false, $args = array() ) { | ||
| if ( isset( $this->registered[ $id ] ) ) { | ||
| $this->registered[ $id ]['enqueue'] = true; | ||
| } elseif ( $src ) { | ||
| $this->register( $id, $src, $deps, $version ); | ||
| $this->register( $id, $src, $deps, $version, $args ); | ||
| $this->registered[ $id ]['enqueue'] = true; | ||
| } else { | ||
| $this->enqueued_before_registered[ $id ] = true; | ||
|
|
@@ -208,13 +282,15 @@ public function add_hooks() { | |
| */ | ||
| public function print_enqueued_script_modules() { | ||
| foreach ( $this->get_marked_for_enqueue() as $id => $script_module ) { | ||
| wp_print_script_tag( | ||
| array( | ||
| 'type' => 'module', | ||
| 'src' => $this->get_src( $id ), | ||
| 'id' => $id . '-js-module', | ||
| ) | ||
| $args = array( | ||
| 'type' => 'module', | ||
| 'src' => $this->get_src( $id ), | ||
| 'id' => $id . '-js-module', | ||
| ); | ||
| if ( 'auto' !== $script_module['fetchpriority'] ) { | ||
| $args['fetchpriority'] = $script_module['fetchpriority']; | ||
| } | ||
| wp_print_script_tag( $args ); | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -231,9 +307,10 @@ public function print_script_module_preloads() { | |
| // Don't preload if it's marked for enqueue. | ||
| if ( true !== $script_module['enqueue'] ) { | ||
| echo sprintf( | ||
| '<link rel="modulepreload" href="%s" id="%s">', | ||
| '<link rel="modulepreload" href="%s" id="%s"%s>', | ||
| esc_url( $this->get_src( $id ) ), | ||
| esc_attr( $id . '-js-modulepreload' ) | ||
| esc_attr( $id . '-js-modulepreload' ), | ||
| 'auto' !== $script_module['fetchpriority'] ? sprintf( ' fetchpriority="%s"', esc_attr( $script_module['fetchpriority'] ) ) : '' | ||
| ); | ||
| } | ||
| } | ||
|
|
@@ -278,7 +355,9 @@ private function get_import_map(): array { | |
| * | ||
| * @since 6.5.0 | ||
| * | ||
| * @return array[] Script modules marked for enqueue, keyed by script module identifier. | ||
| * @phpstan-return array<string, ScriptModule> | ||
| * | ||
| * @return array<string, array> Script modules marked for enqueue, keyed by script module identifier. | ||
| */ | ||
| private function get_marked_for_enqueue(): array { | ||
| $enqueued = array(); | ||
|
|
@@ -300,6 +379,8 @@ private function get_marked_for_enqueue(): array { | |
| * | ||
| * @since 6.5.0 | ||
| * | ||
| * @phpstan-return array<string, ScriptModule> | ||
| * | ||
| * @param string[] $ids The identifiers of the script modules for which to gather dependencies. | ||
| * @param string[] $import_types Optional. Import types of dependencies to retrieve: 'static', 'dynamic', or both. | ||
| * Default is both. | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -158,6 +158,7 @@ function wp_add_inline_script( $handle, $data, $position = 'after' ) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @since 2.1.0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @since 4.3.0 A return value was added. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @since 6.3.0 The $in_footer parameter of type boolean was overloaded to be an $args parameter of type array. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @since n.e.x.t The $fetchpriority parameter of type string was added to the $args parameter of type array. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @param string $handle Name of the script. Should be unique. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @param string|false $src Full URL of the script, or path of the script relative to the WordPress root directory. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -171,8 +172,9 @@ function wp_add_inline_script( $handle, $data, $position = 'after' ) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * Optional. An array of additional script loading strategies. Default empty array. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * Otherwise, it may be a boolean in which case it determines whether the script is printed in the footer. Default false. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @type string $strategy Optional. If provided, may be either 'defer' or 'async'. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @type bool $in_footer Optional. Whether to print the script in the footer. Default 'false'. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @type string $strategy Optional. If provided, may be either 'defer' or 'async'. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @type bool $in_footer Optional. Whether to print the script in the footer. Default 'false'. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @type string $fetchpriority Optional. The fetch priority for the script. Default 'auto'. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @return bool Whether the script has been registered. True on success, false on failure. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -193,6 +195,9 @@ function wp_register_script( $handle, $src, $deps = array(), $ver = false, $args | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if ( ! empty( $args['strategy'] ) ) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| $wp_scripts->add_data( $handle, 'strategy', $args['strategy'] ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if ( ! empty( $args['fetchpriority'] ) ) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| $wp_scripts->add_data( $handle, 'fetchpriority', $args['fetchpriority'] ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The fetchpriority is checked against an allowlist for modules. I don't see that for scripts. Did I overlook that or should it be included?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @sirreal In the case of classic scripts, the
There isn't any allowlist to default to
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. More than default I'm wondering about accepting arbitrary values. It's not likely harmful, but perhaps I understand it's a well defined set of values: For example: wp_enqueue_script( 'example', '/ex.js', array(), '…' );
wp_scripts()->add_data( 'example', 'fetchpriority', 'silly' );produces <script src="/ex.js?ver=…" id="example-js" fetchpriority="silly"></script>which is… silly 🙂
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's a good point. For wordpress-develop/src/wp-includes/class-wp-scripts.php Lines 811 to 837 in 75fb879
This would make sense to include there as well for |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return $registered; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -339,6 +344,7 @@ function wp_deregister_script( $handle ) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @since 2.1.0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @since 6.3.0 The $in_footer parameter of type boolean was overloaded to be an $args parameter of type array. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @since n.e.x.t The $fetchpriority parameter of type string was added to the $args parameter of type array. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @param string $handle Name of the script. Should be unique. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @param string $src Full URL of the script, or path of the script relative to the WordPress root directory. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -352,8 +358,9 @@ function wp_deregister_script( $handle ) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * Optional. An array of additional script loading strategies. Default empty array. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * Otherwise, it may be a boolean in which case it determines whether the script is printed in the footer. Default false. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @type string $strategy Optional. If provided, may be either 'defer' or 'async'. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @type bool $in_footer Optional. Whether to print the script in the footer. Default 'false'. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @type string $strategy Optional. If provided, may be either 'defer' or 'async'. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @type bool $in_footer Optional. Whether to print the script in the footer. Default 'false'. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @type string $fetchpriority Optional. The fetch priority for the script. Default 'auto'. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| function wp_enqueue_script( $handle, $src = '', $deps = array(), $ver = false, $args = array() ) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -378,6 +385,9 @@ function wp_enqueue_script( $handle, $src = '', $deps = array(), $ver = false, $ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if ( ! empty( $args['strategy'] ) ) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| $wp_scripts->add_data( $_handle[0], 'strategy', $args['strategy'] ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if ( ! empty( $args['fetchpriority'] ) ) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| $wp_scripts->add_data( $_handle[0], 'fetchpriority', $args['fetchpriority'] ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| $wp_scripts->enqueue( $handle ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.