-
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
Conversation
Test using WordPress PlaygroundThe changes in this pull request can previewed and tested using a WordPress Playground instance. WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser. Some things to be aware of
For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation. |
fetchpriority=low by default for script modules and add ability to overridefetchpriority for Scripts and Script Modules
Co-authored-by: Pascal Birchler <swissspidy@git.wordpress.org>
Co-authored-by: Luis Herranz <luisherranz@git.wordpress.org>
| * @phpstan-type ScriptModule array{ | ||
| * src: string, | ||
| * version: string|false|null, | ||
| * enqueue: bool, | ||
| * dependencies: array<array{ id: string, import: 'dynamic'|'static' }>, | ||
| * fetchpriority: 'auto'|'low'|'high', | ||
| * } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added these @phpstan annotations for myself as a safeguard while developing this patch. If others don't want PHPStan annotations in core, I'll remove prior to commit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For better consistency, I think it's better to remove these annotations prior to commit indeed, as this is not something used elsewhere in Core. Also I dunno how the docblock parser will handle these info but I think it's going to add a lot of noise in dockblocks displayed on the generated documentation (same goes for other related phpstan annotations)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed in 74a49e1
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the Core Committers: Use this line as a base for the props when committing in SVN: To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
kraftbj
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tested this for regular scripts and it worked as advertised. I did confirm that add_data checks for is_scalar down the chain so lack of type checking here isn't an issue. The Web API, per MDN, will default to auto if not present or if the value is not valid (low, high, auto).
audrasjb
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
left a comment about phpstan docblock annotations
| * @phpstan-type ScriptModule array{ | ||
| * src: string, | ||
| * version: string|false|null, | ||
| * enqueue: bool, | ||
| * dependencies: array<array{ id: string, import: 'dynamic'|'static' }>, | ||
| * fetchpriority: 'auto'|'low'|'high', | ||
| * } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For better consistency, I think it's better to remove these annotations prior to commit indeed, as this is not something used elsewhere in Core. Also I dunno how the docblock parser will handle these info but I think it's going to add a lot of noise in dockblocks displayed on the generated documentation (same goes for other related phpstan annotations)
|
@westonruter if this is still on track for 6.8.2, note that the PR is conflicting against trunk ;) |
| $wp_scripts->add_data( $handle, 'strategy', $args['strategy'] ); | ||
| } | ||
| if ( ! empty( $args['fetchpriority'] ) ) { | ||
| $wp_scripts->add_data( $handle, 'fetchpriority', $args['fetchpriority'] ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The 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?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sirreal In the case of classic scripts, the fetchpriority is instead being specified when the scripts are registered. The only script which gets low is comment-reply:
| $scripts->add_data( 'comment-reply', 'fetchpriority', 'low' ); // In Chrome this is automatically low due to the async strategy, but in Firefox and Safari the priority is normal/medium. |
There isn't any allowlist to default to low for non-module scripts since there is no generalizable pattern for being able to opt in like there is for script modules with the Interactivity API.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The 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 _doing_it_wrong could be shown and the value discarded if an unsupported fetchpriority is provided.
I understand it's a well defined set of values: high | low | auto.
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 🙂
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a good point. For async/defer, this is handled in the add_data() function:
wordpress-develop/src/wp-includes/class-wp-scripts.php
Lines 811 to 837 in 75fb879
| if ( 'strategy' === $key ) { | |
| if ( ! empty( $value ) && ! $this->is_delayed_strategy( $value ) ) { | |
| _doing_it_wrong( | |
| __METHOD__, | |
| sprintf( | |
| /* translators: 1: $strategy, 2: $handle */ | |
| __( 'Invalid strategy `%1$s` defined for `%2$s` during script registration.' ), | |
| $value, | |
| $handle | |
| ), | |
| '6.3.0' | |
| ); | |
| return false; | |
| } elseif ( ! $this->registered[ $handle ]->src && $this->is_delayed_strategy( $value ) ) { | |
| _doing_it_wrong( | |
| __METHOD__, | |
| sprintf( | |
| /* translators: 1: $strategy, 2: $handle */ | |
| __( 'Cannot supply a strategy `%1$s` for script `%2$s` because it is an alias (it lacks a `src` value).' ), | |
| $value, | |
| $handle | |
| ), | |
| '6.3.0' | |
| ); | |
| return false; | |
| } | |
| } |
This would make sense to include there as well for fetchpriority.
sirreal
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll try to provide an in-depth review early next week, but don't feel obliged to wait for me. I've only reviewed the changes superficially so far.
…into trac-61734
sirreal
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The changes look good to me and work well in my testing.
I would like to check for valid fetchpriority in scripts as discussed in https://github.com/WordPress/wordpress-develop/pull/8815/files#r2314439414, but otherwise this seems ready to merge.
Co-authored-by: sirreal <jonsurrell@git.wordpress.org>
…into trac-61734
|
@sirreal Thank you for the review! I've added checks for valid |
| private function get_registered_script_modules( WP_Script_Modules $script_modules ): array { | ||
| $reflection_class = new ReflectionClass( $script_modules ); | ||
| $registered_property = $reflection_class->getProperty( 'registered' ); | ||
| $registered_property->setAccessible( true ); | ||
| return $registered_property->getValue( $script_modules ); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be nice to do some work on https://core.trac.wordpress.org/ticket/60597 to open modules and not require reflection 🙂
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed. It would be nice if there were more getters and setters, similar to WP_Scripts.
sirreal
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did a quick review of the recent changes and they look good. I did not retest.
A final minor note on data providers which I believe should be static. I think this is ready 👍
Co-authored-by: Jon Surrell <sirreal@users.noreply.github.com>
* 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 [WordPress/gutenberg#71366 Gutenberg#71366]. * The `comment-reply` script. * Improve type checks and type hints. Developed in [#8815 GitHub PR], with [WordPress/gutenberg#70173 companion for Gutenberg]. Props westonruter, jonsurrell, swissspidy, luisherranz, kraftbj, audrasjb, dennysdionigi. Fixes #61734. git-svn-id: https://develop.svn.wordpress.org/trunk@60704 602fd350-edb4-49c9-b593-d223f7449a82
* 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 [WordPress/gutenberg#71366 Gutenberg#71366]. * The `comment-reply` script. * Improve type checks and type hints. Developed in [WordPress/wordpress-develop#8815 GitHub PR], with [WordPress/gutenberg#70173 companion for Gutenberg]. Props westonruter, jonsurrell, swissspidy, luisherranz, kraftbj, audrasjb, dennysdionigi. Fixes #61734. Built from https://develop.svn.wordpress.org/trunk@60704 git-svn-id: http://core.svn.wordpress.org/trunk@60040 1a063a9b-81f0-0310-95a4-ce76da25c4cd
* 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 [WordPress/gutenberg#71366 Gutenberg#71366]. * The `comment-reply` script. * Improve type checks and type hints. Developed in [WordPress/wordpress-develop#8815 GitHub PR], with [WordPress/gutenberg#70173 companion for Gutenberg]. Props westonruter, jonsurrell, swissspidy, luisherranz, kraftbj, audrasjb, dennysdionigi. Fixes #61734. Built from https://develop.svn.wordpress.org/trunk@60704 git-svn-id: https://core.svn.wordpress.org/trunk@60040 1a063a9b-81f0-0310-95a4-ce76da25c4cd
|
I just started trying using Gemini to code review patches. I hadn't done it for this PR, so I'm doing so retroactively: Output:
|
* 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 [WordPress/gutenberg#71366 Gutenberg#71366]. * The `comment-reply` script. * Improve type checks and type hints. Developed in [WordPress#8815 GitHub PR], with [WordPress/gutenberg#70173 companion for Gutenberg]. Props westonruter, jonsurrell, swissspidy, luisherranz, kraftbj, audrasjb, dennysdionigi. Fixes #61734. git-svn-id: https://develop.svn.wordpress.org/trunk@60704 602fd350-edb4-49c9-b593-d223f7449a82
fetchpriorityargument to go alongside the loadingstrategy(async&defer) when registering scripts viawp_register_script()/wp_enqueue_script(). This is a follow-up to the script loading strategies introduced in Core-12009.$argsparameter towp_register_script_module()/wp_enqueue_script_module()(and their corresponding methods) to mirror the same 5th$argsparameter used inwp_register_script()/wp_enqeue_script(). This$argsparameter samefetchpriorityargument introduced for non-script modules. (Note that module scripts have adeferloading strategy by default, so adding support for astrategywould only be useful forasync. This is not in the scope of this PR.) This will apply thefetchpriorityattribute both to theSCRIPT[type="module"]tags as well as theLINK[rel="modulepreload"]tags for static import dependencies.WP_Script_Modules::set_fetchpriority( string $id, string $priority )method is added which allows the priority of registered scripts to be changed.fetchpriorityvalue for both scripts and script modules isauto.fetchpriorityattribute is emitted onSCRIPTandLINKtags, it is omitted if the value isautosince this is the default value.comment-replyscript is given an explicitfetchpriorityoflow. While the script is already registered with theasyncloading strategy which Chrome causes the resource to be downloaded with alowpriority by default, this is not the case for Safari or Firefox which use a default medium/normal priority. So the explicitlowpriority reduces the chance that the loading of thecomment-replyscript will interfere with the loading of resources needed in the critical rendering path (e.g. an LCP image element).fetchpriorityoflow. The very first requirement/goal defined for the Interactivity API was for server-side rendering, therefore blocks should not depend on the view module script for initial rendering.Note
If Gutenberg is active, you won't see any changes without WordPress/gutenberg#70173 also checked out.
Trac ticket: https://core.trac.wordpress.org/ticket/61734
Follow ups:
block.jsonschema to allowfetchpriorityandin_footerto be specified for view scripts/modules gutenberg#71366Related:
This Pull Request is for code review only. Please keep all other discussion in the Trac ticket. Do not merge this Pull Request. See GitHub Pull Requests for Code Review in the Core Handbook for more details.
Gemini Summary
This pull request introduces support for the
fetchpriorityattribute on scripts and script modules, allowing for more granular control over resource loading priority.Key Changes:
fetchpriorityfor Scripts & Modules:wp_register_script(),wp_enqueue_script(),wp_register_script_module(), andwp_enqueue_script_module()functions now accept afetchprioritykey in their$argsarray.'high','low', and'auto'. Invalid values will trigger a_doing_it_wrong()notice.fetchpriorityattribute is added to the corresponding<script>and<link rel="modulepreload">tags.Performance Optimizations:
fetchpriority="low"by default, as they are not considered critical for the initial page render.comment-replyscript is also now loaded withfetchpriority="low".New API Methods:
wp_script_modules()->set_fetchpriority()method has been added to modify the fetch priority of an already-registered script module.Testing:
fetchpriorityfunctionality for both classic scripts and script modules, including tests for invalid values and edge cases.This is a non-breaking, additive change that provides a new tool for performance optimization.
Commit Message
Script Loader: Introduce
fetchpriorityfor Scripts and Script Modules.fetchpriorityofauto(default),high,low:fetchpriorityarg to go alongside thestrategyarg which was added for loading scripts with thedeferandasyncloading strategies. See #12009.$argsarray parameter with afetchprioritykey to thewp_register_script_module(), andwp_enqueue_script_module()functions (and their respective underlyingWP_Script_Modules::register()andWP_Script_Modules::enqueue()methods). This$argsparameter corresponds with the same parameter used when registering non-module scripts.WP_Script_Modules::set_fetchpriority()to override thefetchpriorityfor what was previously registered._doing_it_wrong()warning when an invalidfetchpriorityvalue is used, and whenfetchpriorityis added to a script alias.fetchpriorityas an attribute on printedSCRIPTtags as well as on preloadLINKtags for static script module dependencies.fetchpriorityoflowby default for:block.jsonschema to allowfetchpriorityandin_footerto be specified for view scripts/modules gutenberg#71366.comment-replyscript.Developed in: #8815
Companion PR: WordPress/gutenberg#70173
Props westonruter, jonsurrell, swissspidy, luisherranz, kraftbj, audrasjb, dennysdionigi.
Fixes #61734.