Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Use print_scripts_array filter instead of wp_print_scripts action
  • Loading branch information
westonruter committed Sep 26, 2024
commit 0c2d7b23b70b4ede5abc30ff54e922e3594ba97d
37 changes: 21 additions & 16 deletions plugins/web-worker-offloading/hooks.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,30 +70,35 @@ function wwo_register_default_scripts( WP_Scripts $scripts ): void {
add_action( 'wp_default_scripts', 'wwo_register_default_scripts' );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!


/**
* Adds `web-worker-offloading` as dependency to scripts with `worker` data. Also, marks their strategy as `async`.
* Prepends web-worker-offloading to the list of scripts to print if one of the queued scripts is offloaded to a worker.
*
* This is needed because scripts offloaded to a worker thread can be considered async. However, they may include `before` and `after` inline
* scripts that need sequential execution. Once marked as async, `filter_eligible_strategies()` determines if the
* script is eligible for async execution. If so, it will be offloaded to the worker thread.
* This also marks their strategy as `async`. This is needed because scripts offloaded to a worker thread can be
* considered async. However, they may include `before` and `after` inline scripts that need sequential execution. Once
* marked as async, `filter_eligible_strategies()` determines if the script is eligible for async execution. If so, it
* will be offloaded to the worker thread.
*
* @since n.e.x.t
* @since 0.1.0
*
* @param string[]|mixed $to_do An array of enqueued script dependency handles.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is $script_handles changed to $to_do?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, because this is the name of the param passed to print_scripts_array. But I can change it back.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reverted in bfb9e11

* @return string[] Script handles.
*/
function wwo_update_worker_scripts_deps_and_strategy(): void {
foreach ( wp_scripts()->registered as $dep ) {
if (
(bool) wp_scripts()->get_data( $dep->handle, 'worker' ) &&
! in_array( 'web-worker-offloading', wp_scripts()->registered[ $dep->handle ]->deps, true )
) {
wp_scripts()->registered[ $dep->handle ]->deps[] = 'web-worker-offloading';
function wwo_filter_print_scripts_array( $to_do ): array {
$scripts = wp_scripts();
foreach ( (array) $to_do as $handle ) {
if ( true === $scripts->get_data( $handle, 'worker' ) ) {
$scripts->set_group( 'web-worker-offloading', false, 0 ); // Try to print in the head.
array_unshift( $to_do, 'web-worker-offloading' );

if ( false === wp_scripts()->get_data( $dep->handle, 'strategy' ) ) {
wp_script_add_data( $dep->handle, 'strategy', 'async' ); // The 'defer' strategy would work as well.
wp_script_add_data( $dep->handle, 'wwo_strategy_added', true );
// TODO: This should be reconsidered because scripts needing to be offloaded will often have after scripts. See <https://github.com/WordPress/performance/pull/1497/files#r1733538721>.
if ( false === wp_scripts()->get_data( $handle, 'strategy' ) ) {
wp_script_add_data( $handle, 'strategy', 'async' ); // The 'defer' strategy would work as well.
wp_script_add_data( $handle, 'wwo_strategy_added', true );
}
}
}
return $to_do;
}
add_action( 'wp_print_scripts', 'wwo_update_worker_scripts_deps_and_strategy' );
add_filter( 'print_scripts_array', 'wwo_filter_print_scripts_array' );

/**
* Updates script type for handles having `web-worker-offloading` as dependency.
Expand Down
63 changes: 49 additions & 14 deletions plugins/web-worker-offloading/tests/test-web-worker-offloading.php
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ public static function data_update_script_types(): array {
* Test `wwo_update_script_type`.
*
* @covers ::wwo_update_script_type
* @covers ::wwo_update_worker_scripts_deps_and_strategy
* @covers ::wwo_filter_print_scripts_array
*
* @dataProvider data_update_script_types
*
Expand All @@ -187,19 +187,7 @@ public static function data_update_script_types(): array {
* @param bool $doing_it_wrong Whether to expect a `_doing_it_wrong` notice.
*/
public function test_update_script_types( Closure $set_up, string $expected, bool $doing_it_wrong ): void {
$wwo_config_data = wp_scripts()->get_inline_script_data( 'web-worker-offloading', 'before' );
$wwo_inline_script_data = wp_scripts()->get_inline_script_data( 'web-worker-offloading', 'after' );

$expected = str_replace(
'{{ wwo_config }}',
wp_get_inline_script_tag( $wwo_config_data, array( 'id' => 'web-worker-offloading-js-before' ) ),
$expected
);
$expected = str_replace(
'{{ wwo_inline_script }}',
wp_get_inline_script_tag( $wwo_inline_script_data, array( 'id' => 'web-worker-offloading-js-after' ) ),
$expected
);
$expected = $this->replace_placeholders( $expected );

if ( $doing_it_wrong ) {
$this->setExpectedIncorrectUsage( 'wwo_update_script_type' );
Expand All @@ -214,6 +202,53 @@ public function test_update_script_types( Closure $set_up, string $expected, boo
$this->assertEquals( $expected, $actual );
}


/**
* Test head and footer scripts.
*
* @covers ::wwo_update_script_type
* @covers ::wwo_filter_print_scripts_array
*/
public function test_head_and_footer_scripts(): void {
wp_enqueue_script( 'foo', 'https://example.com/foo.js', array(), '1.0.0', false );
wp_script_add_data( 'foo', 'worker', true );

$this->assertEquals(
$this->replace_placeholders( '{{ wwo_config }}{{ wwo_inline_script }}<script type="text/partytown" src="https://example.com/foo.js?ver=1.0.0" id="foo-js" ></script>' ),
trim( get_echo( 'wp_print_head_scripts' ) )
);

wp_enqueue_script( 'bar', 'https://example.com/bar.js', array(), '1.0.0', true );
wp_script_add_data( 'bar', 'worker', true );

$this->assertEquals(
$this->replace_placeholders( '<script type="text/partytown" src="https://example.com/bar.js?ver=1.0.0" id="bar-js" ></script>' ),
trim( get_echo( 'wp_print_footer_scripts' ) )
);
}

/**
* Replace placeholders.
*
* @param string $template Template.
* @return string Template with placeholders replaced.
*/
private function replace_placeholders( string $template ): string {
$wwo_config_data = wp_scripts()->get_inline_script_data( 'web-worker-offloading', 'before' );
$wwo_inline_script_data = wp_scripts()->get_inline_script_data( 'web-worker-offloading', 'after' );

$template = str_replace(
'{{ wwo_config }}',
wp_get_inline_script_tag( $wwo_config_data, array( 'id' => 'web-worker-offloading-js-before' ) ),
$template
);
return str_replace(
'{{ wwo_inline_script }}',
wp_get_inline_script_tag( $wwo_inline_script_data, array( 'id' => 'web-worker-offloading-js-after' ) ),
$template
);
}

/**
* Reset WP_Scripts and WP_Styles.
*/
Expand Down