From eb523a18ce9efac960fcbd6656fe116b926dd5f6 Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Fri, 27 Sep 2024 11:29:09 -0700 Subject: [PATCH 01/24] Add helper.php --- plugins/web-worker-offloading/helper.php | 36 ++++++++++++++++++++++++ plugins/web-worker-offloading/hooks.php | 25 ---------------- plugins/web-worker-offloading/load.php | 2 +- 3 files changed, 37 insertions(+), 26 deletions(-) create mode 100644 plugins/web-worker-offloading/helper.php diff --git a/plugins/web-worker-offloading/helper.php b/plugins/web-worker-offloading/helper.php new file mode 100644 index 0000000000..ae455067e6 --- /dev/null +++ b/plugins/web-worker-offloading/helper.php @@ -0,0 +1,36 @@ + wp_parse_url( plugin_dir_url( __FILE__ ), PHP_URL_PATH ) . 'build/', + 'forward' => array(), + ); + + /** + * Add configuration for Web Worker Offloading. + * + * @since 0.1.0 + * @link https://partytown.builder.io/configuration + * + * @param array{ debug?: bool, forward?: non-empty-string[], lib: non-empty-string, loadScriptsOnMainThread?: non-empty-string[], nonce?: non-empty-string } $config Configuration for Partytown. + */ + return apply_filters( 'wwo_configuration', $config ); +} diff --git a/plugins/web-worker-offloading/hooks.php b/plugins/web-worker-offloading/hooks.php index d6ae5d9be4..5b250de039 100644 --- a/plugins/web-worker-offloading/hooks.php +++ b/plugins/web-worker-offloading/hooks.php @@ -10,31 +10,6 @@ exit; // Exit if accessed directly. } -/** - * Gets configuration for Web Worker Offloading. - * - * @since 0.1.0 - * @link https://partytown.builder.io/configuration - * - * @return array{ debug?: bool, forward?: non-empty-string[], lib: non-empty-string, loadScriptsOnMainThread?: non-empty-string[], nonce?: non-empty-string } Configuration for Partytown. - */ -function wwo_get_configuration(): array { - $config = array( - 'lib' => wp_parse_url( plugin_dir_url( __FILE__ ), PHP_URL_PATH ) . 'build/', - 'forward' => array(), - ); - - /** - * Add configuration for Web Worker Offloading. - * - * @since 0.1.0 - * @link https://partytown.builder.io/configuration - * - * @param array{ debug?: bool, forward?: non-empty-string[], lib: non-empty-string, loadScriptsOnMainThread?: non-empty-string[], nonce?: non-empty-string } $config Configuration for Partytown. - */ - return apply_filters( 'wwo_configuration', $config ); -} - /** * Registers defaults scripts for Web Worker Offloading. * diff --git a/plugins/web-worker-offloading/load.php b/plugins/web-worker-offloading/load.php index a7cd25d486..459cd92041 100644 --- a/plugins/web-worker-offloading/load.php +++ b/plugins/web-worker-offloading/load.php @@ -45,5 +45,5 @@ define( 'WEB_WORKER_OFFLOADING_VERSION', '0.1.0' ); -// Load the hooks. +require_once __DIR__ . '/helper.php'; require_once __DIR__ . '/hooks.php'; From f430916ee6870270b6e4847611ba109cc9132b00 Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Fri, 27 Sep 2024 12:44:19 -0700 Subject: [PATCH 02/24] Improve normalization in tests --- .../tests/test-web-worker-offloading.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/plugins/web-worker-offloading/tests/test-web-worker-offloading.php b/plugins/web-worker-offloading/tests/test-web-worker-offloading.php index e13598d03b..6ae6110f2b 100644 --- a/plugins/web-worker-offloading/tests/test-web-worker-offloading.php +++ b/plugins/web-worker-offloading/tests/test-web-worker-offloading.php @@ -195,9 +195,14 @@ public function test_update_script_types( Closure $set_up, string $expected, boo $set_up(); + $normalize = static function ( $html ) { + $html = preg_replace( '/\r|\n/', '', $html ); + return trim( preg_replace( '#(?=<[^/])#', "\n", $html ) ); + }; + // Normalize the output. - $actual = preg_replace( '/\r|\n/', '', get_echo( 'wp_print_scripts' ) ); - $expected = preg_replace( '/\r|\n/', '', $expected ); + $actual = $normalize( get_echo( 'wp_print_scripts' ) ); + $expected = $normalize( $expected ); $this->assertEquals( $expected, $actual ); } From 84fc20498bb864b6bf7c09344b356f8974aecd44 Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Fri, 27 Sep 2024 12:56:48 -0700 Subject: [PATCH 03/24] Offload inline scripts to web worker as well --- plugins/web-worker-offloading/hooks.php | 47 +++++------ .../tests/test-web-worker-offloading.php | 84 ++++++++++--------- 2 files changed, 67 insertions(+), 64 deletions(-) diff --git a/plugins/web-worker-offloading/hooks.php b/plugins/web-worker-offloading/hooks.php index 5b250de039..70fc7f6426 100644 --- a/plugins/web-worker-offloading/hooks.php +++ b/plugins/web-worker-offloading/hooks.php @@ -63,12 +63,6 @@ function wwo_filter_print_scripts_array( $script_handles ): array { if ( true === (bool) $scripts->get_data( $handle, 'worker' ) ) { $scripts->set_group( 'web-worker-offloading', false, 0 ); // Try to print in the head. array_unshift( $script_handles, 'web-worker-offloading' ); - - // TODO: This should be reconsidered because scripts needing to be offloaded will often have after scripts. See . - 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 $script_handles; @@ -95,25 +89,7 @@ function wwo_update_script_type( $tag, string $handle ) { if ( $html_processor->get_attribute( 'id' ) !== "{$handle}-js" ) { continue; } - if ( null === $html_processor->get_attribute( 'async' ) && null === $html_processor->get_attribute( 'defer' ) ) { - _doing_it_wrong( - 'wwo_update_script_type', - esc_html( - sprintf( - /* translators: %s: script handle */ - __( 'Unable to offload "%s" script to a worker. Script will continue to load in the main thread.', 'web-worker-offloading' ), - $handle - ) - ), - 'Web Worker Offloading 0.1.0' - ); - } else { - $html_processor->set_attribute( 'type', 'text/partytown' ); - } - if ( true === wp_scripts()->get_data( $handle, 'wwo_strategy_added' ) ) { - $html_processor->remove_attribute( 'async' ); - $html_processor->remove_attribute( 'data-wp-strategy' ); - } + $html_processor->set_attribute( 'type', 'text/partytown' ); $tag = $html_processor->get_updated_html(); } } @@ -121,3 +97,24 @@ function wwo_update_script_type( $tag, string $handle ) { return $tag; } add_filter( 'script_loader_tag', 'wwo_update_script_type', 10, 2 ); + +/** + * Filters inline script attributes to offload to a worker if the script has been opted-in. + * + * @param array|mixed $attributes Attributes. + * @return array Attributes. + */ +function wwo_filter_inline_script_attributes( $attributes ): array { + $attributes = (array) $attributes; + if ( + isset( $attributes['id'] ) + && + 1 === preg_match( '/^(?P.+)-js-(?:before|after)$/', $attributes['id'], $matches ) + && + (bool) wp_scripts()->get_data( $matches['handle'], 'worker' ) + ) { + $attributes['type'] = 'text/partytown'; + } + return $attributes; +} +add_filter( 'wp_inline_script_attributes', 'wwo_filter_inline_script_attributes' ); diff --git a/plugins/web-worker-offloading/tests/test-web-worker-offloading.php b/plugins/web-worker-offloading/tests/test-web-worker-offloading.php index 6ae6110f2b..abe82615d0 100644 --- a/plugins/web-worker-offloading/tests/test-web-worker-offloading.php +++ b/plugins/web-worker-offloading/tests/test-web-worker-offloading.php @@ -93,83 +93,93 @@ public function test_wwo_register_default_scripts(): void { public static function data_update_script_types(): array { return array( 'add-script' => array( - 'set_up' => static function (): void { + 'set_up' => static function (): void { wp_enqueue_script( 'foo', 'https://example.com/foo.js', array(), '1.0.0', true ); }, - 'expected' => '', - 'doing_it_wrong' => false, + 'expected' => '', + ), + 'add-inline-scripts' => array( + 'set_up' => static function (): void { + wp_register_script( 'foo', false, array(), '1.0.0' ); + wp_add_inline_script( 'foo', 'console.log("Hello, World!");', 'before' ); + wp_add_inline_script( 'foo', 'console.log("Hello, World!");', 'after' ); + wp_enqueue_script( 'foo' ); + }, + 'expected' => '', ), 'add-script-for-web-worker-offloading' => array( - 'set_up' => static function (): void { + 'set_up' => static function (): void { wp_enqueue_script( 'foo', 'https://example.com/foo.js', array(), '1.0.0', true ); wp_script_add_data( 'foo', 'worker', true ); }, - 'expected' => '{{ wwo_config }}{{ wwo_inline_script }}', - 'doing_it_wrong' => false, + 'expected' => '{{ wwo_config }}{{ wwo_inline_script }}', ), 'add-defer-script-for-web-worker-offloading' => array( - 'set_up' => static function (): void { + 'set_up' => static function (): void { wp_enqueue_script( 'foo', 'https://example.com/foo.js', array(), '1.0.0', array( 'strategy' => 'defer' ) ); wp_script_add_data( 'foo', 'worker', 1 ); }, - 'expected' => '{{ wwo_config }}{{ wwo_inline_script }}', - 'doing_it_wrong' => false, + 'expected' => '{{ wwo_config }}{{ wwo_inline_script }}', ), 'add-async-script-for-web-worker-offloading' => array( - 'set_up' => static function (): void { + 'set_up' => static function (): void { wp_enqueue_script( 'foo', 'https://example.com/foo.js', array(), '1.0.0', array( 'strategy' => 'async' ) ); wp_script_add_data( 'foo', 'worker', true ); }, - 'expected' => '{{ wwo_config }}{{ wwo_inline_script }}', - 'doing_it_wrong' => false, + 'expected' => '{{ wwo_config }}{{ wwo_inline_script }}', ), 'add-script-for-web-worker-offloading-with-before-data' => array( - 'set_up' => static function (): void { + 'set_up' => static function (): void { wp_enqueue_script( 'foo', 'https://example.com/foo.js', array(), '1.0.0', true ); wp_add_inline_script( 'foo', 'console.log("Hello, World!");', 'before' ); wp_script_add_data( 'foo', 'worker', true ); }, - 'expected' => '{{ wwo_config }}{{ wwo_inline_script }}', - 'doing_it_wrong' => false, + 'expected' => '{{ wwo_config }}{{ wwo_inline_script }}', ), 'add-script-for-web-worker-offloading-with-after-data' => array( - 'set_up' => static function (): void { + 'set_up' => static function (): void { wp_enqueue_script( 'foo', 'https://example.com/foo.js', array(), '1.0.0', true ); wp_add_inline_script( 'foo', 'console.log("Hello, World!");', 'after' ); wp_script_add_data( 'foo', 'worker', true ); }, - 'expected' => '{{ wwo_config }}{{ wwo_inline_script }}', - 'doing_it_wrong' => true, + 'expected' => '{{ wwo_config }}{{ wwo_inline_script }}', ), 'add-script-for-web-worker-offloading-with-before-and-after-data' => array( - 'set_up' => static function (): void { + 'set_up' => static function (): void { wp_enqueue_script( 'foo', 'https://example.com/foo.js', array(), '1.0.0', true ); wp_add_inline_script( 'foo', 'console.log("Hello, World!");', 'before' ); wp_add_inline_script( 'foo', 'console.log("Hello, World!");', 'after' ); wp_script_add_data( 'foo', 'worker', true ); }, - 'expected' => '{{ wwo_config }}{{ wwo_inline_script }}', - 'doing_it_wrong' => true, + 'expected' => '{{ wwo_config }}{{ wwo_inline_script }}', ), 'add-async-script-for-web-worker-offloading-with-before-and-after-data' => array( - 'set_up' => static function (): void { + 'set_up' => static function (): void { wp_enqueue_script( 'foo', 'https://example.com/foo.js', array(), '1.0.0', array( 'strategy' => 'async' ) ); wp_add_inline_script( 'foo', 'console.log("Hello, World!");', 'before' ); wp_add_inline_script( 'foo', 'console.log("Hello, World!");', 'after' ); wp_script_add_data( 'foo', 'worker', true ); }, - 'expected' => '{{ wwo_config }}{{ wwo_inline_script }}', - 'doing_it_wrong' => true, + 'expected' => '{{ wwo_config }}{{ wwo_inline_script }}', ), 'add-defer-script-for-web-worker-offloading-with-before-and-after-data' => array( - 'set_up' => static function (): void { + 'set_up' => static function (): void { wp_enqueue_script( 'foo', 'https://example.com/foo.js', array(), '1.0.0', array( 'strategy' => 'defer' ) ); wp_add_inline_script( 'foo', 'console.log("Hello, World!");', 'before' ); wp_add_inline_script( 'foo', 'console.log("Hello, World!");', 'after' ); wp_script_add_data( 'foo', 'worker', true ); }, - 'expected' => '{{ wwo_config }}{{ wwo_inline_script }}', - 'doing_it_wrong' => true, + 'expected' => '{{ wwo_config }}{{ wwo_inline_script }}', + ), + 'add-inline-script-offloaded-to-web-worker' => array( + 'set_up' => static function (): void { + wp_register_script( 'foo', false, array(), '1.0.0' ); + wp_add_inline_script( 'foo', 'console.log("Hello, World!");', 'before' ); + wp_add_inline_script( 'foo', 'console.log("Hello, World!");', 'after' ); + wp_script_add_data( 'foo', 'worker', true ); + wp_enqueue_script( 'foo' ); + }, + 'expected' => '{{ wwo_config }}{{ wwo_inline_script }}', ), ); } @@ -179,20 +189,16 @@ public static function data_update_script_types(): array { * * @covers ::wwo_update_script_type * @covers ::wwo_filter_print_scripts_array + * @cogers ::wwo_filter_inline_script_attributes * * @dataProvider data_update_script_types * - * @param Closure $set_up Closure to set up the test. - * @param string $expected Expected output. - * @param bool $doing_it_wrong Whether to expect a `_doing_it_wrong` notice. + * @param Closure $set_up Closure to set up the test. + * @param string $expected Expected output. */ - public function test_update_script_types( Closure $set_up, string $expected, bool $doing_it_wrong ): void { + public function test_update_script_types( Closure $set_up, string $expected ): void { $expected = $this->replace_placeholders( $expected ); - if ( $doing_it_wrong ) { - $this->setExpectedIncorrectUsage( 'wwo_update_script_type' ); - } - $set_up(); $normalize = static function ( $html ) { @@ -218,7 +224,7 @@ public function test_head_and_footer_scripts(): void { wp_script_add_data( 'foo', 'worker', true ); $this->assertEquals( - $this->replace_placeholders( '{{ wwo_config }}{{ wwo_inline_script }}' ), + $this->replace_placeholders( '{{ wwo_config }}{{ wwo_inline_script }}' ), trim( get_echo( 'wp_print_head_scripts' ) ) ); @@ -226,7 +232,7 @@ public function test_head_and_footer_scripts(): void { wp_script_add_data( 'bar', 'worker', true ); $this->assertEquals( - $this->replace_placeholders( '' ), + $this->replace_placeholders( '' ), trim( get_echo( 'wp_print_footer_scripts' ) ) ); } @@ -242,7 +248,7 @@ public function test_only_head_script(): void { wp_script_add_data( 'foo', 'worker', true ); $this->assertEquals( - $this->replace_placeholders( '{{ wwo_config }}{{ wwo_inline_script }}' ), + $this->replace_placeholders( '{{ wwo_config }}{{ wwo_inline_script }}' ), trim( get_echo( 'wp_print_head_scripts' ) ) ); @@ -272,7 +278,7 @@ public function test_only_footer_script(): void { wp_script_add_data( 'bar', 'worker', true ); $this->assertEquals( - $this->replace_placeholders( '{{ wwo_config }}{{ wwo_inline_script }}' ), + $this->replace_placeholders( '{{ wwo_config }}{{ wwo_inline_script }}' ), trim( get_echo( 'wp_print_footer_scripts' ) ) ); } From 796996e50c69df6116504085259e4a6be75a1003 Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Fri, 27 Sep 2024 12:59:11 -0700 Subject: [PATCH 04/24] Add WooCommerce integration with Google Analytics --- plugins/web-worker-offloading/load.php | 1 + plugins/web-worker-offloading/readme.txt | 12 ++- plugins/web-worker-offloading/third-party.php | 76 +++++++++++++++++++ .../third-party/woocommerce.php | 15 ++++ 4 files changed, 102 insertions(+), 2 deletions(-) create mode 100644 plugins/web-worker-offloading/third-party.php create mode 100644 plugins/web-worker-offloading/third-party/woocommerce.php diff --git a/plugins/web-worker-offloading/load.php b/plugins/web-worker-offloading/load.php index 459cd92041..27973a3394 100644 --- a/plugins/web-worker-offloading/load.php +++ b/plugins/web-worker-offloading/load.php @@ -47,3 +47,4 @@ require_once __DIR__ . '/helper.php'; require_once __DIR__ . '/hooks.php'; +require_once __DIR__ . '/third-party.php'; diff --git a/plugins/web-worker-offloading/readme.txt b/plugins/web-worker-offloading/readme.txt index 774ff9139d..27d251fe74 100644 --- a/plugins/web-worker-offloading/readme.txt +++ b/plugins/web-worker-offloading/readme.txt @@ -11,15 +11,23 @@ Offload JavaScript execution to a Web Worker. == Description == -This plugin offloads JavaScript execution to a Web Worker, improving performance by freeing up the main thread. +This plugin offloads JavaScript execution to a Web Worker, improving performance by freeing up the main thread. This should translate into improved [Interaction to Next Paint](https://web.dev/articles/inp) (INP) scores. _This functionality is considered experimental._ -In order to opt-in a script to be loaded in a worker, simply add `worker` script data to a registered script. For example, +In order to opt in a script to be loaded in a worker, simply add `worker` script data to a registered script. For example, if you have a script registered with the handle of `foo`, opt-in to offload it to a web worker by doing: ` wp_script_add_data( 'foo', 'worker', true ); ` +Otherwise, the plugin currently ships with built-in integrations to offload Google Analytics to a web worker for the following plugins: + +* [Rank Math SEO](https://wordpress.org/plugins/seo-by-rank-math/) +* [Site Kit by Google](https://wordpress.org/plugins/google-site-kit/) +* [WooCommerce](https://wordpress.org/plugins/woocommerce/) + +Please monitor your analytics once activating to ensure all the expected events are being logged. At the same time, monitor your INP scores to check for improvement. + == Frequently Asked Questions == = Why are my offloaded scripts not working and I see a 404 error in the console for `partytown-sandbox-sw.html`? = diff --git a/plugins/web-worker-offloading/third-party.php b/plugins/web-worker-offloading/third-party.php new file mode 100644 index 0000000000..29111254a4 --- /dev/null +++ b/plugins/web-worker-offloading/third-party.php @@ -0,0 +1,76 @@ +|mixed $configuration Configuration. + * @return array Configuration. + */ +function wwo_add_google_analytics_forwarded_events( $configuration ): array { + $configuration = (array) $configuration; + + $configuration['forward'][] = 'dataLayer.push'; + return $configuration; +} + +/** + * Adds a script to be offloaded to a worker. + * + * @param string $script_handle Script handle. + */ +function wwo_mark_script_for_offloading( string $script_handle ): void { + add_filter( + 'print_scripts_array', + static function ( $script_handles ) use ( $script_handle ) { + if ( in_array( $script_handle, (array) $script_handles, true ) ) { + wp_script_add_data( $script_handle, 'worker', true ); + } + return $script_handles; + } + ); +} + +/** + * Loads third party plugin integrations for active plugins. + * + * @since 0.1.0 + */ +function wwo_load_third_party_integrations(): void { + $plugins_with_integrations = array( + // TODO: google-site-kit. + // TODO: seo-by-rank-math. + 'woocommerce', + ); + + // Load corresponding file for each string in $plugins if the WordPress plugin is installed and active. + $active_plugin_slugs = array_filter( + array_map( + static function ( $plugin_file ) { + if ( is_string( $plugin_file ) && str_contains( $plugin_file, '/' ) ) { + return strtok( $plugin_file, '/' ); + } else { + return false; + } + }, + (array) get_option( 'active_plugins' ) + ) + ); + + foreach ( array_intersect( $active_plugin_slugs, $plugins_with_integrations ) as $plugin_slug ) { + require_once __DIR__ . '/third-party/' . $plugin_slug . '.php'; + } +} +add_action( 'plugins_loaded', 'wwo_load_third_party_integrations' ); diff --git a/plugins/web-worker-offloading/third-party/woocommerce.php b/plugins/web-worker-offloading/third-party/woocommerce.php new file mode 100644 index 0000000000..1f7e2c278c --- /dev/null +++ b/plugins/web-worker-offloading/third-party/woocommerce.php @@ -0,0 +1,15 @@ + Date: Sat, 28 Sep 2024 15:52:10 -0700 Subject: [PATCH 05/24] Clean up wwo_update_script_type() logic --- plugins/web-worker-offloading/hooks.php | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/plugins/web-worker-offloading/hooks.php b/plugins/web-worker-offloading/hooks.php index 70fc7f6426..e07882ea30 100644 --- a/plugins/web-worker-offloading/hooks.php +++ b/plugins/web-worker-offloading/hooks.php @@ -47,11 +47,6 @@ function wwo_register_default_scripts( WP_Scripts $scripts ): void { /** * Prepends web-worker-offloading to the list of scripts to print if one of the queued scripts is offloaded to a worker. * - * 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 0.1.0 * * @param string[]|mixed $script_handles An array of enqueued script dependency handles. @@ -80,20 +75,19 @@ function wwo_filter_print_scripts_array( $script_handles ): array { */ function wwo_update_script_type( $tag, string $handle ) { if ( - is_string( $tag ) && + is_string( $tag ) + && (bool) wp_scripts()->get_data( $handle, 'worker' ) ) { $html_processor = new WP_HTML_Tag_Processor( $tag ); - while ( $html_processor->next_tag( array( 'tag_name' => 'SCRIPT' ) ) ) { - if ( $html_processor->get_attribute( 'id' ) !== "{$handle}-js" ) { - continue; + if ( $html_processor->get_attribute( 'id' ) === "{$handle}-js" ) { + $html_processor->set_attribute( 'type', 'text/partytown' ); + $tag = $html_processor->get_updated_html(); + break; } - $html_processor->set_attribute( 'type', 'text/partytown' ); - $tag = $html_processor->get_updated_html(); } } - return $tag; } add_filter( 'script_loader_tag', 'wwo_update_script_type', 10, 2 ); From c2d73f0ded33049f59a3162eda00bf423edc6b21 Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Sat, 28 Sep 2024 17:02:42 -0700 Subject: [PATCH 06/24] Avoid prepending WWO script multiple times and only do so at end of print_scripts_array filtering --- plugins/web-worker-offloading/hooks.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/web-worker-offloading/hooks.php b/plugins/web-worker-offloading/hooks.php index e07882ea30..178093c28e 100644 --- a/plugins/web-worker-offloading/hooks.php +++ b/plugins/web-worker-offloading/hooks.php @@ -58,11 +58,12 @@ function wwo_filter_print_scripts_array( $script_handles ): array { if ( true === (bool) $scripts->get_data( $handle, 'worker' ) ) { $scripts->set_group( 'web-worker-offloading', false, 0 ); // Try to print in the head. array_unshift( $script_handles, 'web-worker-offloading' ); + break; } } return $script_handles; } -add_filter( 'print_scripts_array', 'wwo_filter_print_scripts_array' ); +add_filter( 'print_scripts_array', 'wwo_filter_print_scripts_array', PHP_INT_MAX ); /** * Updates script type for handles having `web-worker-offloading` as dependency. From 844884ce2eee978fc0af445c3269788a4e3dc7a8 Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Sat, 28 Sep 2024 17:04:37 -0700 Subject: [PATCH 07/24] Update wwo_mark_script_for_offloading() to pass multiple script handles --- plugins/web-worker-offloading/third-party.php | 15 ++++++++------- .../third-party/woocommerce.php | 8 ++++++-- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/plugins/web-worker-offloading/third-party.php b/plugins/web-worker-offloading/third-party.php index 29111254a4..8ec48b593b 100644 --- a/plugins/web-worker-offloading/third-party.php +++ b/plugins/web-worker-offloading/third-party.php @@ -27,18 +27,19 @@ function wwo_add_google_analytics_forwarded_events( $configuration ): array { } /** - * Adds a script to be offloaded to a worker. + * Adds scripts to be offloaded to a worker. * - * @param string $script_handle Script handle. + * @param string[] $script_handles Script handles. */ -function wwo_mark_script_for_offloading( string $script_handle ): void { +function wwo_mark_scripts_for_offloading( array $script_handles ): void { add_filter( 'print_scripts_array', - static function ( $script_handles ) use ( $script_handle ) { - if ( in_array( $script_handle, (array) $script_handles, true ) ) { - wp_script_add_data( $script_handle, 'worker', true ); + static function ( $to_do ) use ( $script_handles ) { + $worker_script_handles = array_intersect( (array) $to_do, $script_handles ); + foreach ( $worker_script_handles as $worker_script_handle ) { + wp_script_add_data( $worker_script_handle, 'worker', true ); } - return $script_handles; + return $to_do; } ); } diff --git a/plugins/web-worker-offloading/third-party/woocommerce.php b/plugins/web-worker-offloading/third-party/woocommerce.php index 1f7e2c278c..703d8726ae 100644 --- a/plugins/web-worker-offloading/third-party/woocommerce.php +++ b/plugins/web-worker-offloading/third-party/woocommerce.php @@ -11,5 +11,9 @@ } add_filter( 'wwo_configuration', 'wwo_add_google_analytics_forwarded_events' ); -wwo_mark_script_for_offloading( 'google-tag-manager' ); -wwo_mark_script_for_offloading( 'woocommerce-google-analytics-integration-gtag' ); +wwo_mark_scripts_for_offloading( + array( + 'google-tag-manager', + 'woocommerce-google-analytics-integration-gtag', + ) +); From fc70dec3eb350e7e931c643e2cf998638acde73b Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Sat, 28 Sep 2024 17:09:18 -0700 Subject: [PATCH 08/24] Enable Partytown debug when WP_DEBUG and SCRIPT_DEBUG --- plugins/web-worker-offloading/helper.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugins/web-worker-offloading/helper.php b/plugins/web-worker-offloading/helper.php index ae455067e6..b5ca92c68e 100644 --- a/plugins/web-worker-offloading/helper.php +++ b/plugins/web-worker-offloading/helper.php @@ -24,6 +24,10 @@ function wwo_get_configuration(): array { 'forward' => array(), ); + if ( WP_DEBUG && SCRIPT_DEBUG ) { + $config['debug'] = true; + } + /** * Add configuration for Web Worker Offloading. * From 5986738e825f26ab13562acf142ade7f56546b46 Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Sat, 28 Sep 2024 22:01:24 -0700 Subject: [PATCH 09/24] Add WooCommerce-specific configuration --- plugins/web-worker-offloading/third-party.php | 16 -------------- .../third-party/woocommerce.php | 22 ++++++++++++++++++- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/plugins/web-worker-offloading/third-party.php b/plugins/web-worker-offloading/third-party.php index 8ec48b593b..660ceb3738 100644 --- a/plugins/web-worker-offloading/third-party.php +++ b/plugins/web-worker-offloading/third-party.php @@ -10,22 +10,6 @@ exit; // Exit if accessed directly. } -/** - * Adds forwarded events for Google Analytics. - * - * @since 0.1.0 - * @link https://partytown.builder.io/google-tag-manager#forward-events - * - * @param array|mixed $configuration Configuration. - * @return array Configuration. - */ -function wwo_add_google_analytics_forwarded_events( $configuration ): array { - $configuration = (array) $configuration; - - $configuration['forward'][] = 'dataLayer.push'; - return $configuration; -} - /** * Adds scripts to be offloaded to a worker. * diff --git a/plugins/web-worker-offloading/third-party/woocommerce.php b/plugins/web-worker-offloading/third-party/woocommerce.php index 703d8726ae..b2dea0df5d 100644 --- a/plugins/web-worker-offloading/third-party/woocommerce.php +++ b/plugins/web-worker-offloading/third-party/woocommerce.php @@ -10,10 +10,30 @@ exit; // Exit if accessed directly. } -add_filter( 'wwo_configuration', 'wwo_add_google_analytics_forwarded_events' ); +/** + * Configures WWO for WooCommerce and Google Analytics. + * + * @since 0.1.0 + * @link https://partytown.builder.io/google-tag-manager#forward-events + * + * @param array|mixed $configuration Configuration. + * @return array Configuration. + */ +function wwo_woocommerce_configure( $configuration ): array { + $configuration = (array) $configuration; + + $configuration['mainWindowAccessors'][] = 'wp'; // Because woocommerce-google-analytics-integration needs to access wp.i18n. + $configuration['globalFns'][] = 'gtag'; // Because gtag() is defined in one script and called in another. + $configuration['forward'][] = 'dataLayer.push'; // Because the Partytown integration has this in its example config. + return $configuration; +} +add_filter( 'wwo_configuration', 'wwo_woocommerce_configure' ); + wwo_mark_scripts_for_offloading( array( 'google-tag-manager', + 'woocommerce-google-analytics-integration', + 'woocommerce-google-analytics-integration-data', 'woocommerce-google-analytics-integration-gtag', ) ); From d1886260911e560b7868c5730c7dbbc9cd73daba Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Sat, 28 Sep 2024 23:13:24 -0700 Subject: [PATCH 10/24] Add ga4w to mainWindowAccessors --- plugins/web-worker-offloading/third-party/woocommerce.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/web-worker-offloading/third-party/woocommerce.php b/plugins/web-worker-offloading/third-party/woocommerce.php index b2dea0df5d..15ead6534b 100644 --- a/plugins/web-worker-offloading/third-party/woocommerce.php +++ b/plugins/web-worker-offloading/third-party/woocommerce.php @@ -22,7 +22,8 @@ function wwo_woocommerce_configure( $configuration ): array { $configuration = (array) $configuration; - $configuration['mainWindowAccessors'][] = 'wp'; // Because woocommerce-google-analytics-integration needs to access wp.i18n. + $configuration['mainWindowAccessors'][] = 'wp'; // Because woocommerce-google-analytics-integration needs to access wp.i18n. + $configuration['mainWindowAccessors'][] = 'ga4w'; // Because woocommerce-google-analytics-integration needs to access window.ga4w. $configuration['globalFns'][] = 'gtag'; // Because gtag() is defined in one script and called in another. $configuration['forward'][] = 'dataLayer.push'; // Because the Partytown integration has this in its example config. return $configuration; @@ -33,7 +34,6 @@ function wwo_woocommerce_configure( $configuration ): array { array( 'google-tag-manager', 'woocommerce-google-analytics-integration', - 'woocommerce-google-analytics-integration-data', 'woocommerce-google-analytics-integration-gtag', ) ); From 805ec7033bf6cc93ad8600e2cec649468ceb0597 Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Sat, 28 Sep 2024 23:33:19 -0700 Subject: [PATCH 11/24] Use forked version of Partytown with wp.i18n workaround --- package-lock.json | 5 ++--- package.json | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index fbd71d9dc3..164e1ecbf3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,7 +7,7 @@ "name": "performance", "license": "GPL-2.0-or-later", "dependencies": { - "@builder.io/partytown": "^0.10.2", + "@builder.io/partytown": "github:westonruter/partytown#add/wp-i18n-workaround", "web-vitals": "4.2.3" }, "devDependencies": { @@ -2040,8 +2040,7 @@ }, "node_modules/@builder.io/partytown": { "version": "0.10.2", - "resolved": "https://registry.npmjs.org/@builder.io/partytown/-/partytown-0.10.2.tgz", - "integrity": "sha512-A9U+4PREWcS+CCYzKGIPovtGB/PBgnH/8oQyCE6Nr9drDJk6cMPpLQIEajpGPmG9tYF7N3FkRvhXm/AS9+0iKg==", + "resolved": "git+ssh://git@github.com/westonruter/partytown.git#255d06ed3467c5ed9357a9b2a9890e2400cb68c9", "bin": { "partytown": "bin/partytown.cjs" }, diff --git a/package.json b/package.json index 9fe86baf1f..3201b1ec75 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "npm": ">=10.2.3" }, "dependencies": { - "@builder.io/partytown": "^0.10.2", + "@builder.io/partytown": "github:westonruter/partytown#add/wp-i18n-workaround", "web-vitals": "4.2.3" }, "devDependencies": { From efe35061aab613bc492b06c6fa02b1ac78cb251a Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Sat, 28 Sep 2024 23:57:14 -0700 Subject: [PATCH 12/24] Add missing since tag --- plugins/web-worker-offloading/hooks.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/web-worker-offloading/hooks.php b/plugins/web-worker-offloading/hooks.php index 178093c28e..e7638f3c8c 100644 --- a/plugins/web-worker-offloading/hooks.php +++ b/plugins/web-worker-offloading/hooks.php @@ -96,6 +96,8 @@ function wwo_update_script_type( $tag, string $handle ) { /** * Filters inline script attributes to offload to a worker if the script has been opted-in. * + * @since 0.1.0 + * * @param array|mixed $attributes Attributes. * @return array Attributes. */ From e9ac9248901062fd2b3db19100b4397c72c59f4d Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Sun, 29 Sep 2024 00:05:55 -0700 Subject: [PATCH 13/24] Update readme with FAQs and filter docs --- plugins/web-worker-offloading/readme.txt | 28 ++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/plugins/web-worker-offloading/readme.txt b/plugins/web-worker-offloading/readme.txt index 27d251fe74..f504eb85d4 100644 --- a/plugins/web-worker-offloading/readme.txt +++ b/plugins/web-worker-offloading/readme.txt @@ -28,8 +28,36 @@ Otherwise, the plugin currently ships with built-in integrations to offload Goog Please monitor your analytics once activating to ensure all the expected events are being logged. At the same time, monitor your INP scores to check for improvement. +This plugin relies on the [Partytown 🎉](https://partytown.builder.io/) library by Builder.io, released under the MIT license. This library is in beta and there are quite a few [open bugs](https://github.com/BuilderIO/partytown/issues?q=is%3Aopen+is%3Aissue+label%3Abug). The [Partytown configuration](https://partytown.builder.io/configuration) can be modified via the `wwo_configuration` filter. For example: + +` + Date: Sun, 29 Sep 2024 00:10:24 -0700 Subject: [PATCH 14/24] Cast apply_filters() return value to array --- plugins/web-worker-offloading/helper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/web-worker-offloading/helper.php b/plugins/web-worker-offloading/helper.php index b5ca92c68e..48bcab440b 100644 --- a/plugins/web-worker-offloading/helper.php +++ b/plugins/web-worker-offloading/helper.php @@ -36,5 +36,5 @@ function wwo_get_configuration(): array { * * @param array{ debug?: bool, forward?: non-empty-string[], lib: non-empty-string, loadScriptsOnMainThread?: non-empty-string[], nonce?: non-empty-string } $config Configuration for Partytown. */ - return apply_filters( 'wwo_configuration', $config ); + return (array) apply_filters( 'wwo_configuration', $config ); } From ac9c55f1180482bbbd617b89d5b681a664b115c6 Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Sun, 29 Sep 2024 00:15:33 -0700 Subject: [PATCH 15/24] Add private access tags --- plugins/web-worker-offloading/hooks.php | 4 ++++ plugins/web-worker-offloading/third-party.php | 4 ++++ plugins/web-worker-offloading/third-party/woocommerce.php | 1 + 3 files changed, 9 insertions(+) diff --git a/plugins/web-worker-offloading/hooks.php b/plugins/web-worker-offloading/hooks.php index e7638f3c8c..d0c5abd9f1 100644 --- a/plugins/web-worker-offloading/hooks.php +++ b/plugins/web-worker-offloading/hooks.php @@ -14,6 +14,7 @@ * Registers defaults scripts for Web Worker Offloading. * * @since 0.1.0 + * @access private * * @param WP_Scripts $scripts WP_Scripts instance. */ @@ -48,6 +49,7 @@ function wwo_register_default_scripts( WP_Scripts $scripts ): void { * Prepends web-worker-offloading to the list of scripts to print if one of the queued scripts is offloaded to a worker. * * @since 0.1.0 + * @access private * * @param string[]|mixed $script_handles An array of enqueued script dependency handles. * @return string[] Script handles. @@ -69,6 +71,7 @@ function wwo_filter_print_scripts_array( $script_handles ): array { * Updates script type for handles having `web-worker-offloading` as dependency. * * @since 0.1.0 + * @access private * * @param string|mixed $tag Script tag. * @param string $handle Script handle. @@ -97,6 +100,7 @@ function wwo_update_script_type( $tag, string $handle ) { * Filters inline script attributes to offload to a worker if the script has been opted-in. * * @since 0.1.0 + * @access private * * @param array|mixed $attributes Attributes. * @return array Attributes. diff --git a/plugins/web-worker-offloading/third-party.php b/plugins/web-worker-offloading/third-party.php index 660ceb3738..d2731f5cd6 100644 --- a/plugins/web-worker-offloading/third-party.php +++ b/plugins/web-worker-offloading/third-party.php @@ -13,6 +13,9 @@ /** * Adds scripts to be offloaded to a worker. * + * @since 0.1.0 + * @access private + * * @param string[] $script_handles Script handles. */ function wwo_mark_scripts_for_offloading( array $script_handles ): void { @@ -32,6 +35,7 @@ static function ( $to_do ) use ( $script_handles ) { * Loads third party plugin integrations for active plugins. * * @since 0.1.0 + * @access private */ function wwo_load_third_party_integrations(): void { $plugins_with_integrations = array( diff --git a/plugins/web-worker-offloading/third-party/woocommerce.php b/plugins/web-worker-offloading/third-party/woocommerce.php index 15ead6534b..a6ca4c9ffa 100644 --- a/plugins/web-worker-offloading/third-party/woocommerce.php +++ b/plugins/web-worker-offloading/third-party/woocommerce.php @@ -14,6 +14,7 @@ * Configures WWO for WooCommerce and Google Analytics. * * @since 0.1.0 + * @access private * @link https://partytown.builder.io/google-tag-manager#forward-events * * @param array|mixed $configuration Configuration. From a0af3d0a6144115fdccd9e73b9e19a6a3deecd44 Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Sun, 29 Sep 2024 00:18:33 -0700 Subject: [PATCH 16/24] Note additional plugin support for the future --- plugins/web-worker-offloading/readme.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/web-worker-offloading/readme.txt b/plugins/web-worker-offloading/readme.txt index f504eb85d4..aeb3b1c05c 100644 --- a/plugins/web-worker-offloading/readme.txt +++ b/plugins/web-worker-offloading/readme.txt @@ -20,12 +20,12 @@ if you have a script registered with the handle of `foo`, opt-in to offload it t wp_script_add_data( 'foo', 'worker', true ); ` -Otherwise, the plugin currently ships with built-in integrations to offload Google Analytics to a web worker for the following plugins: +Otherwise, the plugin currently ships with built-in integrations to offload Google Analytics to a web worker for the following plugin: -* [Rank Math SEO](https://wordpress.org/plugins/seo-by-rank-math/) -* [Site Kit by Google](https://wordpress.org/plugins/google-site-kit/) * [WooCommerce](https://wordpress.org/plugins/woocommerce/) +Support for [Site Kit by Google](https://wordpress.org/plugins/google-site-kit/) and [Rank Math SEO](https://wordpress.org/plugins/seo-by-rank-math/) are [planned](https://github.com/WordPress/performance/issues/1455). + Please monitor your analytics once activating to ensure all the expected events are being logged. At the same time, monitor your INP scores to check for improvement. This plugin relies on the [Partytown 🎉](https://partytown.builder.io/) library by Builder.io, released under the MIT license. This library is in beta and there are quite a few [open bugs](https://github.com/BuilderIO/partytown/issues?q=is%3Aopen+is%3Aissue+label%3Abug). The [Partytown configuration](https://partytown.builder.io/configuration) can be modified via the `wwo_configuration` filter. For example: From 649e61710ee7ed1563064897206b18f1d054fb40 Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Sun, 29 Sep 2024 00:26:11 -0700 Subject: [PATCH 17/24] Explain that inline before/after scripts are also offloaded to worker --- plugins/web-worker-offloading/readme.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/web-worker-offloading/readme.txt b/plugins/web-worker-offloading/readme.txt index aeb3b1c05c..eb05ed944c 100644 --- a/plugins/web-worker-offloading/readme.txt +++ b/plugins/web-worker-offloading/readme.txt @@ -20,6 +20,8 @@ if you have a script registered with the handle of `foo`, opt-in to offload it t wp_script_add_data( 'foo', 'worker', true ); ` +Unlike with the script loading strategies (async/defer), any inline before/after scripts associated with the worker-offloaded registered script will also be offloaded to the worker, whereas with the script strategies an inline after script would block the script from being delayed. + Otherwise, the plugin currently ships with built-in integrations to offload Google Analytics to a web worker for the following plugin: * [WooCommerce](https://wordpress.org/plugins/woocommerce/) From 74b93c795347f2bdde2e0d35c90bfd0bf0cc455e Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Sun, 29 Sep 2024 09:30:37 -0700 Subject: [PATCH 18/24] Use plugin active tests instead of looking for specific slugs --- plugins/web-worker-offloading/third-party.php | 25 ++++++------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/plugins/web-worker-offloading/third-party.php b/plugins/web-worker-offloading/third-party.php index d2731f5cd6..3f04401815 100644 --- a/plugins/web-worker-offloading/third-party.php +++ b/plugins/web-worker-offloading/third-party.php @@ -41,25 +41,16 @@ function wwo_load_third_party_integrations(): void { $plugins_with_integrations = array( // TODO: google-site-kit. // TODO: seo-by-rank-math. - 'woocommerce', + 'woocommerce' => static function (): bool { + // See . + return class_exists( 'WooCommerce' ); + }, ); - // Load corresponding file for each string in $plugins if the WordPress plugin is installed and active. - $active_plugin_slugs = array_filter( - array_map( - static function ( $plugin_file ) { - if ( is_string( $plugin_file ) && str_contains( $plugin_file, '/' ) ) { - return strtok( $plugin_file, '/' ); - } else { - return false; - } - }, - (array) get_option( 'active_plugins' ) - ) - ); - - foreach ( array_intersect( $active_plugin_slugs, $plugins_with_integrations ) as $plugin_slug ) { - require_once __DIR__ . '/third-party/' . $plugin_slug . '.php'; + foreach ( $plugins_with_integrations as $plugin_slug => $active_callback ) { + if ( $active_callback() ) { + require_once __DIR__ . '/third-party/' . $plugin_slug . '.php'; + } } } add_action( 'plugins_loaded', 'wwo_load_third_party_integrations' ); From 89ea3823c81d17b74570b18390e33891d882f33c Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Sun, 29 Sep 2024 12:54:22 -0700 Subject: [PATCH 19/24] Extend window.partytown if it already exists --- plugins/web-worker-offloading/hooks.php | 2 +- .../tests/test-web-worker-offloading.php | 8 ++++++-- plugins/web-worker-offloading/third-party.php | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/plugins/web-worker-offloading/hooks.php b/plugins/web-worker-offloading/hooks.php index d0c5abd9f1..210b371375 100644 --- a/plugins/web-worker-offloading/hooks.php +++ b/plugins/web-worker-offloading/hooks.php @@ -35,7 +35,7 @@ function wwo_register_default_scripts( WP_Scripts $scripts ): void { $scripts->add_inline_script( 'web-worker-offloading', sprintf( - 'window.partytown = %s;', + 'window.partytown = {...(window.partytown || {}), ...%s};', wp_json_encode( wwo_get_configuration() ) ), 'before' diff --git a/plugins/web-worker-offloading/tests/test-web-worker-offloading.php b/plugins/web-worker-offloading/tests/test-web-worker-offloading.php index abe82615d0..6bab39d0ff 100644 --- a/plugins/web-worker-offloading/tests/test-web-worker-offloading.php +++ b/plugins/web-worker-offloading/tests/test-web-worker-offloading.php @@ -77,8 +77,12 @@ public function test_wwo_register_default_scripts(): void { $this->assertTrue( wp_script_is( 'web-worker-offloading', 'registered' ) ); $this->assertNotEmpty( $before_data ); $this->assertNotEmpty( $after_data ); - $this->assertEquals( - sprintf( 'window.partytown = %s;', wp_json_encode( $partytown_config ) ), + $this->assertStringContainsString( + 'window.partytown', + $before_data + ); + $this->assertStringContainsString( + wp_json_encode( $partytown_config ), $before_data ); $this->assertEquals( file_get_contents( $partytown_lib . 'partytown.js' ), $after_data ); diff --git a/plugins/web-worker-offloading/third-party.php b/plugins/web-worker-offloading/third-party.php index 3f04401815..a1313ee3dd 100644 --- a/plugins/web-worker-offloading/third-party.php +++ b/plugins/web-worker-offloading/third-party.php @@ -16,7 +16,7 @@ * @since 0.1.0 * @access private * - * @param string[] $script_handles Script handles. + * @param non-empty-string[] $script_handles Script handles. */ function wwo_mark_scripts_for_offloading( array $script_handles ): void { add_filter( From 2f38b131ea0ed0cf3184ab7fb087774ada9c9f8b Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Sun, 29 Sep 2024 13:22:28 -0700 Subject: [PATCH 20/24] Facilitate extending Partytown config with non-JSON serializable data --- plugins/web-worker-offloading/helper.php | 38 +++++++++++++++++-- plugins/web-worker-offloading/readme.txt | 38 ++++++++++++++++++- .../tests/test-web-worker-offloading.php | 3 -- 3 files changed, 70 insertions(+), 9 deletions(-) diff --git a/plugins/web-worker-offloading/helper.php b/plugins/web-worker-offloading/helper.php index 48bcab440b..e4567d7313 100644 --- a/plugins/web-worker-offloading/helper.php +++ b/plugins/web-worker-offloading/helper.php @@ -15,13 +15,13 @@ * * @since 0.1.0 * @link https://partytown.builder.io/configuration + * @link https://github.com/BuilderIO/partytown/blob/b292a14047a0c12ca05ba97df1833935d42fdb66/src/lib/types.ts#L393-L548 * - * @return array{ debug?: bool, forward?: non-empty-string[], lib: non-empty-string, loadScriptsOnMainThread?: non-empty-string[], nonce?: non-empty-string } Configuration for Partytown. + * @return array Configuration for Partytown. */ function wwo_get_configuration(): array { $config = array( - 'lib' => wp_parse_url( plugin_dir_url( __FILE__ ), PHP_URL_PATH ) . 'build/', - 'forward' => array(), + 'lib' => wp_parse_url( plugin_dir_url( __FILE__ ), PHP_URL_PATH ) . 'build/', ); if ( WP_DEBUG && SCRIPT_DEBUG ) { @@ -31,10 +31,40 @@ function wwo_get_configuration(): array { /** * Add configuration for Web Worker Offloading. * + * Many of the configuration options are not documented publicly, so refer to the TypeScript definitions. + * Additionally, not all of the configuration options (e.g. functions) can be serialized as JSON and must instead be + * defined in JavaScript instead. To do so, use the following PHP code instead of filtering `wwo_configuration`: + * + * add_action( + * 'wp_enqueue_scripts', + * function () { + * wp_add_inline_script( + * 'web-worker-offloading', + * << { + * if (type === 'script') { + * const proxyUrl = new URL('https://my-reverse-proxy.com/'); + * proxyUrl.searchParams.append('url', url.href); + * return proxyUrl; + * } + * return url; + * }, + * }; + * JS, + * 'before' + * ); + * } + * ); + * + * There are also many configuration options which are not documented, so refer to the TypeScript definitions. + * * @since 0.1.0 * @link https://partytown.builder.io/configuration + * @link https://github.com/BuilderIO/partytown/blob/b292a14047a0c12ca05ba97df1833935d42fdb66/src/lib/types.ts#L393-L548 * - * @param array{ debug?: bool, forward?: non-empty-string[], lib: non-empty-string, loadScriptsOnMainThread?: non-empty-string[], nonce?: non-empty-string } $config Configuration for Partytown. + * @param array $config Configuration for Partytown. */ return (array) apply_filters( 'wwo_configuration', $config ); } diff --git a/plugins/web-worker-offloading/readme.txt b/plugins/web-worker-offloading/readme.txt index eb05ed944c..78eefd5e25 100644 --- a/plugins/web-worker-offloading/readme.txt +++ b/plugins/web-worker-offloading/readme.txt @@ -11,7 +11,9 @@ Offload JavaScript execution to a Web Worker. == Description == -This plugin offloads JavaScript execution to a Web Worker, improving performance by freeing up the main thread. This should translate into improved [Interaction to Next Paint](https://web.dev/articles/inp) (INP) scores. _This functionality is considered experimental._ +This plugin offloads JavaScript execution to a Web Worker, improving performance by freeing up the main thread. This should translate into improved [Interaction to Next Paint](https://web.dev/articles/inp) (INP) scores. + +⚠ _This functionality is experimental._ ⚠ In order to opt in a script to be loaded in a worker, simply add `worker` script data to a registered script. For example, if you have a script registered with the handle of `foo`, opt-in to offload it to a web worker by doing: @@ -30,7 +32,9 @@ Support for [Site Kit by Google](https://wordpress.org/plugins/google-site-kit/) Please monitor your analytics once activating to ensure all the expected events are being logged. At the same time, monitor your INP scores to check for improvement. -This plugin relies on the [Partytown 🎉](https://partytown.builder.io/) library by Builder.io, released under the MIT license. This library is in beta and there are quite a few [open bugs](https://github.com/BuilderIO/partytown/issues?q=is%3Aopen+is%3Aissue+label%3Abug). The [Partytown configuration](https://partytown.builder.io/configuration) can be modified via the `wwo_configuration` filter. For example: +This plugin relies on the [Partytown 🎉](https://partytown.builder.io/) library by Builder.io, released under the MIT license. This library is in beta and there are quite a few [open bugs](https://github.com/BuilderIO/partytown/issues?q=is%3Aopen+is%3Aissue+label%3Abug). + +The [Partytown configuration](https://partytown.builder.io/configuration) can be modified via the `wwo_configuration` filter. For example: ` { + if (type === 'script') { + const proxyUrl = new URL('https://my-reverse-proxy.com/'); + proxyUrl.searchParams.append('url', url.href); + return proxyUrl; + } + return url; + }, + }; + JS, + 'before' + ); + } +); +` + +There are also many configuration options which are not documented, so refer to the [TypeScript definitions](https://github.com/BuilderIO/partytown/blob/b292a14047a0c12ca05ba97df1833935d42fdb66/src/lib/types.ts#L393-L548). + == Frequently Asked Questions == = Why are my offloaded scripts not working and I see a 404 error in the console for `partytown-sandbox-sw.html`? = diff --git a/plugins/web-worker-offloading/tests/test-web-worker-offloading.php b/plugins/web-worker-offloading/tests/test-web-worker-offloading.php index 6bab39d0ff..0d3e6c0f18 100644 --- a/plugins/web-worker-offloading/tests/test-web-worker-offloading.php +++ b/plugins/web-worker-offloading/tests/test-web-worker-offloading.php @@ -33,9 +33,6 @@ public function test_wwo_get_configuration(): void { $config = wwo_get_configuration(); $this->assertArrayHasKey( 'lib', $config ); - $this->assertArrayHasKey( 'forward', $config ); - $this->assertEmpty( $config['forward'] ); - $this->assertIsArray( $config['forward'] ); $this->assertStringStartsWith( '/' . basename( $wp_content_dir ), $config['lib'] ); $this->assertStringEndsWith( $partytown_assets_path, $config['lib'] ); From 41434a24d25e1000f50dbbb6da54da5bfa3bb60e Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Sun, 29 Sep 2024 14:01:12 -0700 Subject: [PATCH 21/24] Add analytics to list of tags --- plugins/web-worker-offloading/readme.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/web-worker-offloading/readme.txt b/plugins/web-worker-offloading/readme.txt index 78eefd5e25..f981eafc4d 100644 --- a/plugins/web-worker-offloading/readme.txt +++ b/plugins/web-worker-offloading/readme.txt @@ -5,7 +5,7 @@ Tested up to: 6.6 Stable tag: 0.1.0 License: GPLv2 or later License URI: https://www.gnu.org/licenses/gpl-2.0.html -Tags: performance, JavaScript, web worker, partytown +Tags: performance, JavaScript, web worker, partytown, analytics Offload JavaScript execution to a Web Worker. From cfea71a21051d5f306f2d89fa14862d7707a8109 Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Sun, 29 Sep 2024 14:02:33 -0700 Subject: [PATCH 22/24] Use example URL --- plugins/web-worker-offloading/helper.php | 2 +- plugins/web-worker-offloading/readme.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/web-worker-offloading/helper.php b/plugins/web-worker-offloading/helper.php index e4567d7313..be6a4a1527 100644 --- a/plugins/web-worker-offloading/helper.php +++ b/plugins/web-worker-offloading/helper.php @@ -45,7 +45,7 @@ function wwo_get_configuration(): array { * ...(window.partytown || {}), * resolveUrl: (url, location, type) => { * if (type === 'script') { - * const proxyUrl = new URL('https://my-reverse-proxy.com/'); + * const proxyUrl = new URL('https://my-reverse-proxy.example.com/'); * proxyUrl.searchParams.append('url', url.href); * return proxyUrl; * } diff --git a/plugins/web-worker-offloading/readme.txt b/plugins/web-worker-offloading/readme.txt index f981eafc4d..02f02af54d 100644 --- a/plugins/web-worker-offloading/readme.txt +++ b/plugins/web-worker-offloading/readme.txt @@ -58,7 +58,7 @@ add_action( ...(window.partytown || {}), resolveUrl: (url, location, type) => { if (type === 'script') { - const proxyUrl = new URL('https://my-reverse-proxy.com/'); + const proxyUrl = new URL('https://my-reverse-proxy.example.com/'); proxyUrl.searchParams.append('url', url.href); return proxyUrl; } From db9d10e1cacd8ffea0cc8c7dea4bdc3d00e42111 Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Sun, 29 Sep 2024 14:10:56 -0700 Subject: [PATCH 23/24] Differentiate before/after inline scripts in tests --- .../tests/test-web-worker-offloading.php | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/plugins/web-worker-offloading/tests/test-web-worker-offloading.php b/plugins/web-worker-offloading/tests/test-web-worker-offloading.php index 0d3e6c0f18..3f0d1e450b 100644 --- a/plugins/web-worker-offloading/tests/test-web-worker-offloading.php +++ b/plugins/web-worker-offloading/tests/test-web-worker-offloading.php @@ -102,11 +102,11 @@ public static function data_update_script_types(): array { 'add-inline-scripts' => array( 'set_up' => static function (): void { wp_register_script( 'foo', false, array(), '1.0.0' ); - wp_add_inline_script( 'foo', 'console.log("Hello, World!");', 'before' ); - wp_add_inline_script( 'foo', 'console.log("Hello, World!");', 'after' ); + wp_add_inline_script( 'foo', 'console.log("Hello, Before World!");', 'before' ); + wp_add_inline_script( 'foo', 'console.log("Hello, After World!");', 'after' ); wp_enqueue_script( 'foo' ); }, - 'expected' => '', + 'expected' => '', ), 'add-script-for-web-worker-offloading' => array( 'set_up' => static function (): void { @@ -132,55 +132,55 @@ public static function data_update_script_types(): array { 'add-script-for-web-worker-offloading-with-before-data' => array( 'set_up' => static function (): void { wp_enqueue_script( 'foo', 'https://example.com/foo.js', array(), '1.0.0', true ); - wp_add_inline_script( 'foo', 'console.log("Hello, World!");', 'before' ); + wp_add_inline_script( 'foo', 'console.log("Hello, Before World!");', 'before' ); wp_script_add_data( 'foo', 'worker', true ); }, - 'expected' => '{{ wwo_config }}{{ wwo_inline_script }}', + 'expected' => '{{ wwo_config }}{{ wwo_inline_script }}', ), 'add-script-for-web-worker-offloading-with-after-data' => array( 'set_up' => static function (): void { wp_enqueue_script( 'foo', 'https://example.com/foo.js', array(), '1.0.0', true ); - wp_add_inline_script( 'foo', 'console.log("Hello, World!");', 'after' ); + wp_add_inline_script( 'foo', 'console.log("Hello, After World!");', 'after' ); wp_script_add_data( 'foo', 'worker', true ); }, - 'expected' => '{{ wwo_config }}{{ wwo_inline_script }}', + 'expected' => '{{ wwo_config }}{{ wwo_inline_script }}', ), 'add-script-for-web-worker-offloading-with-before-and-after-data' => array( 'set_up' => static function (): void { wp_enqueue_script( 'foo', 'https://example.com/foo.js', array(), '1.0.0', true ); - wp_add_inline_script( 'foo', 'console.log("Hello, World!");', 'before' ); - wp_add_inline_script( 'foo', 'console.log("Hello, World!");', 'after' ); + wp_add_inline_script( 'foo', 'console.log("Hello, Before World!");', 'before' ); + wp_add_inline_script( 'foo', 'console.log("Hello, After World!");', 'after' ); wp_script_add_data( 'foo', 'worker', true ); }, - 'expected' => '{{ wwo_config }}{{ wwo_inline_script }}', + 'expected' => '{{ wwo_config }}{{ wwo_inline_script }}', ), 'add-async-script-for-web-worker-offloading-with-before-and-after-data' => array( 'set_up' => static function (): void { wp_enqueue_script( 'foo', 'https://example.com/foo.js', array(), '1.0.0', array( 'strategy' => 'async' ) ); - wp_add_inline_script( 'foo', 'console.log("Hello, World!");', 'before' ); - wp_add_inline_script( 'foo', 'console.log("Hello, World!");', 'after' ); + wp_add_inline_script( 'foo', 'console.log("Hello, Before World!");', 'before' ); + wp_add_inline_script( 'foo', 'console.log("Hello, After World!");', 'after' ); wp_script_add_data( 'foo', 'worker', true ); }, - 'expected' => '{{ wwo_config }}{{ wwo_inline_script }}', + 'expected' => '{{ wwo_config }}{{ wwo_inline_script }}', ), 'add-defer-script-for-web-worker-offloading-with-before-and-after-data' => array( 'set_up' => static function (): void { wp_enqueue_script( 'foo', 'https://example.com/foo.js', array(), '1.0.0', array( 'strategy' => 'defer' ) ); - wp_add_inline_script( 'foo', 'console.log("Hello, World!");', 'before' ); - wp_add_inline_script( 'foo', 'console.log("Hello, World!");', 'after' ); + wp_add_inline_script( 'foo', 'console.log("Hello, Before World!");', 'before' ); + wp_add_inline_script( 'foo', 'console.log("Hello, After World!");', 'after' ); wp_script_add_data( 'foo', 'worker', true ); }, - 'expected' => '{{ wwo_config }}{{ wwo_inline_script }}', + 'expected' => '{{ wwo_config }}{{ wwo_inline_script }}', ), 'add-inline-script-offloaded-to-web-worker' => array( 'set_up' => static function (): void { wp_register_script( 'foo', false, array(), '1.0.0' ); - wp_add_inline_script( 'foo', 'console.log("Hello, World!");', 'before' ); - wp_add_inline_script( 'foo', 'console.log("Hello, World!");', 'after' ); + wp_add_inline_script( 'foo', 'console.log("Hello, Before World!");', 'before' ); + wp_add_inline_script( 'foo', 'console.log("Hello, After World!");', 'after' ); wp_script_add_data( 'foo', 'worker', true ); wp_enqueue_script( 'foo' ); }, - 'expected' => '{{ wwo_config }}{{ wwo_inline_script }}', + 'expected' => '{{ wwo_config }}{{ wwo_inline_script }}', ), ); } From 998d19f60ef03a202818201ee1299e175ff5b713 Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Mon, 30 Sep 2024 11:46:05 -0700 Subject: [PATCH 24/24] Revert "Remove web-worker-offloading from plugins.json for now since it is not yet ready for release." This reverts commit 16222c11153d6a5bee5f860e11ef960d657c9c80. --- plugins.json | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins.json b/plugins.json index b24b2db70c..9fa07ba6e7 100644 --- a/plugins.json +++ b/plugins.json @@ -7,6 +7,7 @@ "optimization-detective", "performance-lab", "speculation-rules", + "web-worker-offloading", "webp-uploads" ] }