[wp-trac] [WordPress Trac] #61734: Add the ability to handle "fetchpriority" to ES Modules and Import Maps
WordPress Trac
noreply at wordpress.org
Wed Jul 31 23:07:38 UTC 2024
#61734: Add the ability to handle "fetchpriority" to ES Modules and Import Maps
---------------------------+--------------------------------------
Reporter: dennysdionigi | Owner: westonruter
Type: enhancement | Status: accepted
Priority: normal | Milestone: 6.7
Component: Script Loader | Version: 6.5
Severity: minor | Resolution:
Keywords: needs-patch | Focuses: javascript, performance
---------------------------+--------------------------------------
Changes (by westonruter):
* keywords: => needs-patch
* owner: (none) => westonruter
* version: 6.6.1 => 6.5
* status: new => accepted
* milestone: Awaiting Review => 6.7
Comment:
I do indeed see that on a page with the Interactivity API present for the
Image block and the Navigation block, that these scripts are all loaded
with '''high priority''' in Chrome:
* `/wp-includes/blocks/navigation/view.js`
* `/wp-includes/blocks/image/view.js`
* `/wp-includes/js/dist/interactivity.js`
The HTML in question:
{{{
<script type="importmap" id="wp-importmap">
{"imports":{"@wordpress\/interactivity":"http:\/\/localhost:8888\/wp-
includes\/js\/dist\/interactivity.js?ver=6.7-alpha-58835"}}
</script>
<script type="module" src="http://localhost:8888/wp-
includes/blocks/navigation/view.js?ver=6.7-alpha-58835" id="@wordpress
/block-library/navigation-js-module"></script>
<script type="module" src="http://localhost:8888/wp-
includes/blocks/image/view.js?ver=6.7-alpha-58835" id="@wordpress/block-
library/image-js-module"></script>
<link rel="modulepreload" href="http://localhost:8888/wp-
includes/js/dist/interactivity.js?ver=6.7-alpha-58835" id="@wordpress
/interactivity-js-modulepreload">
}}}
This doesn't seem ideal, considering that server-side rendering should be
employed by interactive blocks, meaning that the scripting should not be
in the critical path for rendering the page. By loading these scripts with
high priority, they may be hurting LCP by adding network contention for
fetching the LCP image.
For adding `fetchpriority` for a script module, either this could be added
to the `script` tag itself or it could be added as a
`link[rel=modulepreload]` tag that the same `src`.
For traditional scripts and module scripts alike, you can use the
`wp_script_attributes` filter to inject the `fetchpriority` attribute onto
the `script` tag. For example, to mark all module scripts to load with
`fetchpriority=low`:
{{{#!php
<?php
add_filter(
'wp_script_attributes',
static function ( $attributes ) {
if (
isset( $attributes['type'], $attributes['id'] ) &&
'module' === $attributes['type'] &&
str_starts_with( $attributes['id'], '@wordpress
/block-library/' )
) {
$attributes['fetchpriority'] = 'low';
}
return $attributes;
}
);
}}}
However, this does not help when a script module is not directly enqueued
in which case a `link[rel=modulepreload]` is added via
`WP_Script_Modules::print_script_module_preloads()` which normally occurs
for the `@wordpress/interactivity` script. And there is no way to insert
`fetchpriority=low` into the generated `link` tag without some hacking:
{{{#!php
<?php
add_action(
'init',
static function () {
$position = wp_is_block_theme() ? 'wp_head' : 'wp_footer';
$priority = has_action( $position, array(
wp_script_modules(), 'print_script_module_preloads' ) );
if ( false === $priority ) {
return;
}
remove_action( $position, array( wp_script_modules(),
'print_script_module_preloads' ), $priority );
add_action(
$position,
static function () {
ob_start();
wp_script_modules()->print_script_module_preloads();
$buffer = ob_get_clean();
if ( '' === $buffer ) {
return;
}
$processor = new WP_HTML_Tag_Processor(
$buffer );
while ( $processor->next_tag( array(
'tag_name' => 'LINK' ) ) ) {
$processor->set_attribute(
'fetchpriority', 'low' );
}
echo $processor->get_updated_html();
},
$priority
);
}
);
}}}
I put these snippets in a plugin you can use for testing as well:
https://gist.github.com/westonruter/471111a891f43e0f48bc7e0ca478623d
Given a test post using the TT4 theme that contains one lightbox-enabled
Image block which is the LCP element, where the responsive Navigation
block is also present:
I tried [https://github.com/GoogleChromeLabs/wpp-research/tree/main/cli
#benchmark-web-vitals benchmarking] page loads with the existing behavior
where all scripts are loaded with high priority, and over 100 requests the
median LCP-TTFB was 48.15 ms.
Then I tried adding `fetchpriority=low` to the scripts, and over 100
requests the median LCP-TTFB was 44.6 ms.
'''So adding `fetchpriority=low` makes the LCP metric here 7.37%
faster.'''
(The TTFB-LCP metric here is the LCP discounting variations in TTFB.)
I think the Interactivity API should add `fetchpriority=low` to all of the
module scripts it registers.
--
Ticket URL: <https://core.trac.wordpress.org/ticket/61734#comment:2>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform
More information about the wp-trac
mailing list