Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
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
3 changes: 2 additions & 1 deletion src/wp-includes/blocks.php
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,8 @@ function register_block_script_module_id( $metadata, $field_name, $index = 0 ) {
( isset( $metadata['supports']['interactivity'] ) && true === $metadata['supports']['interactivity'] ) ||
( isset( $metadata['supports']['interactivity']['interactive'] ) && true === $metadata['supports']['interactivity']['interactive'] )
) {
$args['fetchpriority'] = 'low';
$args['fetchpriority'] = 'low';
$args['load_on_client_navigation'] = true;

Choose a reason for hiding this comment

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

There could be interactive blocks that don't support client-side navigation. I guess it's not important in this case because navigation doesn't happen when the target page contains any of these blocks, although we could prevent downloading some bytes here if we only set true for those that support client navigation.

cc: @luisherranz

Copy link
Member

Choose a reason for hiding this comment

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

There could be interactive blocks that don't support client-side navigation

Do you mean supports.interactivity = { interactive: true, clientNavigation: false }?

Choose a reason for hiding this comment

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

Yup, that's the case I have in mind.

Copy link
Member

Choose a reason for hiding this comment

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

Yes, we should take that into account 🙂

}

wp_register_script_module(
Expand Down
20 changes: 14 additions & 6 deletions src/wp-includes/class-wp-script-modules.php
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,9 @@ class WP_Script_Modules {
* @param array $args {
* Optional. An array of additional args. Default empty array.
*
* @type 'auto'|'low'|'high' $fetchpriority Fetch priority. Default 'auto'. Optional.
* @type 'auto'|'low'|'high' $fetchpriority Fetch priority. Default 'auto'. Optional.
* @type bool $load_on_client_navigation Whether the script module should be loaded on client
* navigation. Default false. Optional.
* }
*/
public function register( string $id, string $src, array $deps = array(), $version = false, array $args = array() ) {
Expand Down Expand Up @@ -129,10 +131,11 @@ public function register( string $id, string $src, array $deps = array(), $versi
}

$this->registered[ $id ] = array(
'src' => $src,
'version' => $version,
'dependencies' => $dependencies,
'fetchpriority' => $fetchpriority,
'src' => $src,
'version' => $version,
'dependencies' => $dependencies,
'fetchpriority' => $fetchpriority,
'load_on_client_navigation' => isset( $args['load_on_client_navigation'] ) ? $args['load_on_client_navigation'] : false,
);
}
}
Expand Down Expand Up @@ -217,7 +220,9 @@ public function set_fetchpriority( string $id, string $priority ): bool {
* @param array $args {
* Optional. An array of additional args. Default empty array.
*
* @type 'auto'|'low'|'high' $fetchpriority Fetch priority. Default 'auto'. Optional.
* @type 'auto'|'low'|'high' $fetchpriority Fetch priority. Default 'auto'. Optional.
* @type bool $load_on_client_navigation Whether the script module should be loaded on client
* navigation. Default false. Optional.
* }
*/
public function enqueue( string $id, string $src = '', array $deps = array(), $version = false, array $args = array() ) {
Expand Down Expand Up @@ -332,6 +337,9 @@ public function print_enqueued_script_modules() {
if ( $fetchpriority !== $script_module['fetchpriority'] ) {
$args['data-wp-fetchpriority'] = $script_module['fetchpriority'];
}
if ( isset( $script_module['load_on_client_navigation'] ) && true === $script_module['load_on_client_navigation'] ) {
$args['data-wp-router-options'] = '{ "loadOnClientNavigation": true }';
}
wp_print_script_tag( $args );
}
}
Expand Down
8 changes: 6 additions & 2 deletions src/wp-includes/script-modules.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,9 @@ function wp_script_modules(): WP_Script_Modules {
* @param array $args {
* Optional. An array of additional args. Default empty array.
*
* @type 'auto'|'low'|'high' $fetchpriority Fetch priority. Default 'auto'. Optional.
* @type 'auto'|'low'|'high' $fetchpriority Fetch priority. Default 'auto'. Optional.
* @type bool $load_on_client_navigation Whether the script module should be loaded on client
* navigation. Default false. Optional.
* }
*/
function wp_register_script_module( string $id, string $src, array $deps = array(), $version = false, array $args = array() ) {
Expand Down Expand Up @@ -107,7 +109,9 @@ function wp_register_script_module( string $id, string $src, array $deps = array
* @param array $args {
* Optional. An array of additional args. Default empty array.
*
* @type 'auto'|'low'|'high' $fetchpriority Fetch priority. Default 'auto'. Optional.
* @type 'auto'|'low'|'high' $fetchpriority Fetch priority. Default 'auto'. Optional.
* @type bool $load_on_client_navigation Whether the script module should be loaded on client
* navigation. Default false. Optional.
* }
*/
function wp_enqueue_script_module( string $id, string $src = '', array $deps = array(), $version = false, array $args = array() ) {
Expand Down
92 changes: 92 additions & 0 deletions tests/phpunit/tests/blocks/register.php
Original file line number Diff line number Diff line change
Expand Up @@ -1512,4 +1512,96 @@ public function test_register_block_type_from_metadata_with_windows_path() {

$this->assertNotFalse( register_block_type_from_metadata( $windows_like_path ) );
}

/**
* Tests that load_on_client_navigation is set to true for blocks with interactivity support.
*
* @covers ::register_block_script_module_id
*/
public function test_register_block_script_module_id_with_interactivity_support() {
global $wp_script_modules;
$wp_script_modules = null;

$metadata = array(
'file' => DIR_TESTDATA . '/blocks/notice/block.json',
'name' => 'tests/interactive-block',
'viewScriptModule' => 'file:./block.js',
'supports' => array(
'interactivity' => true,
),
);

$result = register_block_script_module_id( $metadata, 'viewScriptModule' );

$this->assertSame( 'tests-interactive-block-view-script-module', $result );

// Enqueue and verify the script module has the data-wp-router-options attribute.
wp_enqueue_script_module( 'tests-interactive-block-view-script-module' );

$output = get_echo( array( wp_script_modules(), 'print_enqueued_script_modules' ) );

$this->assertStringContainsString( 'data-wp-router-options=', $output );
$this->assertStringContainsString( 'loadOnClientNavigation', $output );
}

/**
* Tests that load_on_client_navigation is set to true for blocks with interactive flag.
*
* @covers ::register_block_script_module_id
*/
public function test_register_block_script_module_id_with_interactive_flag() {
global $wp_script_modules;
$wp_script_modules = null;

$metadata = array(
'file' => DIR_TESTDATA . '/blocks/notice/block.json',
'name' => 'tests/interactive-block-2',
'viewScriptModule' => 'file:./block.js',
'supports' => array(
'interactivity' => array(
'interactive' => true,
),
),
);

$result = register_block_script_module_id( $metadata, 'viewScriptModule' );

$this->assertSame( 'tests-interactive-block-2-view-script-module', $result );

// Enqueue and verify the script module has the data-wp-router-options attribute.
wp_enqueue_script_module( 'tests-interactive-block-2-view-script-module' );

$output = get_echo( array( wp_script_modules(), 'print_enqueued_script_modules' ) );

$this->assertStringContainsString( 'data-wp-router-options=', $output );
$this->assertStringContainsString( 'loadOnClientNavigation', $output );
}

/**
* Tests that load_on_client_navigation is not set for blocks without interactivity support.
*
* @covers ::register_block_script_module_id
*/
public function test_register_block_script_module_id_without_interactivity_support() {
global $wp_script_modules;
$wp_script_modules = null;

$metadata = array(
'file' => DIR_TESTDATA . '/blocks/notice/block.json',
'name' => 'tests/non-interactive-block',
'viewScriptModule' => 'file:./block.js',
);

$result = register_block_script_module_id( $metadata, 'viewScriptModule' );

$this->assertSame( 'tests-non-interactive-block-view-script-module', $result );

// Enqueue and verify the script module does not have the data-wp-router-options attribute.
wp_enqueue_script_module( 'tests-non-interactive-block-view-script-module' );

$output = get_echo( array( wp_script_modules(), 'print_enqueued_script_modules' ) );

$this->assertStringContainsString( 'tests-non-interactive-block-view-script-module', $output );
$this->assertStringNotContainsString( 'data-wp-router-options=', $output );
}
}
89 changes: 89 additions & 0 deletions tests/phpunit/tests/script-modules/wpScriptModules.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ public function get_enqueued_script_modules(): array {

$id = preg_replace( '/-js-module$/', '', (string) $p->get_attribute( 'id' ) );
$fetchpriority = $p->get_attribute( 'fetchpriority' );
$router_options = $p->get_attribute( 'data-wp-router-options' );
$modules[ $id ] = array_merge(
array(
'url' => $p->get_attribute( 'src' ),
Expand All @@ -79,6 +80,9 @@ static function ( $attribute_name ) use ( $p ) {
$p->get_attribute_names_with_prefix( 'data-' )
)
);
if ( is_string( $router_options ) ) {
$modules[ $id ]['data-wp-router-options'] = json_decode( $router_options, true );
}
}

return $modules;
Expand Down Expand Up @@ -1728,4 +1732,89 @@ public static function data_invalid_script_module_data(): array {
'string' => array( 'string' ),
);
}

/**
* Tests that load_on_client_navigation defaults to false when registering a script module.
*
* @covers WP_Script_Modules::register
*/
public function test_load_on_client_navigation_defaults_to_false_for_registered_modules() {
$this->script_modules->register( 'foo', '/foo.js' );
$registered_modules = $this->get_registered_script_modules( $this->script_modules );
$this->assertFalse( $registered_modules['foo']['load_on_client_navigation'] );
}

/**
* Tests that load_on_client_navigation can be set to true when registering a script module.
*
* @covers WP_Script_Modules::register
*/
public function test_load_on_client_navigation_true_for_registered_modules() {
$this->script_modules->register( 'foo', '/foo.js', array(), false, array( 'load_on_client_navigation' => true ) );
$registered_modules = $this->get_registered_script_modules( $this->script_modules );
$this->assertSame( true, $registered_modules['foo']['load_on_client_navigation'] );
}

/**
* Tests that load_on_client_navigation can be set to false when registering a script module.
*
* @covers WP_Script_Modules::register
*/
public function test_load_on_client_navigation_false_for_registered_modules() {
$this->script_modules->register( 'foo', '/foo.js', array(), false, array( 'load_on_client_navigation' => false ) );
$registered_modules = $this->get_registered_script_modules( $this->script_modules );
$this->assertSame( false, $registered_modules['foo']['load_on_client_navigation'] );
}

/**
* Tests that load_on_client_navigation attribute is not added by default for enqueued script modules.
*
* @covers WP_Script_Modules::register
* @covers WP_Script_Modules::enqueue
* @covers WP_Script_Modules::print_enqueued_script_modules
*/
public function test_load_on_client_navigation_default_for_enqueued_modules() {
$this->script_modules->register( 'foo', '/foo.js' );
$this->script_modules->enqueue( 'foo' );

$enqueued_script_modules = $this->get_enqueued_script_modules();

$this->assertCount( 1, $enqueued_script_modules );
$this->assertArrayNotHasKey( 'data-wp-router-options', $enqueued_script_modules['foo'] );
}

/**
* Tests that load_on_client_navigation attribute is added when set to true for enqueued script modules.
*
* @covers WP_Script_Modules::register
* @covers WP_Script_Modules::enqueue
* @covers WP_Script_Modules::print_enqueued_script_modules
*/
public function test_load_on_client_navigation_true_for_enqueued_modules() {
$this->script_modules->register( 'foo', '/foo.js', array(), false, array( 'load_on_client_navigation' => true ) );
$this->script_modules->enqueue( 'foo' );

$enqueued_script_modules = $this->get_enqueued_script_modules();

$this->assertCount( 1, $enqueued_script_modules );
$this->assertArrayHasKey( 'data-wp-router-options', $enqueued_script_modules['foo'] );
$this->assertSame( array( 'loadOnClientNavigation' => true ), $enqueued_script_modules['foo']['data-wp-router-options'] );
}

/**
* Tests that load_on_client_navigation attribute is not added when set to false for enqueued script modules.
*
* @covers WP_Script_Modules::register
* @covers WP_Script_Modules::enqueue
* @covers WP_Script_Modules::print_enqueued_script_modules
*/
public function test_load_on_client_navigation_false_for_enqueued_modules() {
$this->script_modules->register( 'foo', '/foo.js', array(), false, array( 'load_on_client_navigation' => false ) );
$this->script_modules->enqueue( 'foo' );

$enqueued_script_modules = $this->get_enqueued_script_modules();

$this->assertCount( 1, $enqueued_script_modules );
$this->assertArrayNotHasKey( 'data-wp-router-options', $enqueued_script_modules['foo'] );
}
}
Loading