Skip to content
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

Blocks: Add handling for block.json viewScriptModule #58731

Merged
merged 4 commits into from
Feb 7, 2024
Merged
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
33 changes: 28 additions & 5 deletions docs/reference-guides/block-api/block-metadata.md
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,26 @@ It's possible to pass a script handle registered with the [`wp_register_script`]

_Note: An option to pass also an array of view scripts exists since WordPress `6.1.0`._

### View script

- Type: `WPDefinedAsset`|`WPDefinedAsset[]` ([learn more](#wpdefinedasset))
- Optional
- Localized: No
- Property: `viewScript`
- Since: `WordPress 5.9.0`
sirreal marked this conversation as resolved.
Show resolved Hide resolved

```json
{ "viewScriptModule": [ "file:./view.js", "example-shared-script-module-id" ] }
```

Block type frontend script module definition. They will be enqueued only when viewing the content on the front of the site.

It's possible to pass a script module ID registered with the [`wp_register_script_module`](https://developer.wordpress.org/reference/functions/wp_register_script_module/) function, a path to a JavaScript module relative to the `block.json` file, or a list with a mix of both ([learn more](#wpdefinedasset)).

WordPress scripts and WordPress script modules are not compatible at the moment. If frontend view assets depend on WordPress scripts, `viewScript` should be used. If they depend on WordPress script modules —the Interactivity API at this time— `viewScriptModule` should be used. In the future, it will be possible to depend on scripts from script modules.

_Note: Available since WordPress `6.5.0`._

### Editor style

- Type: `WPDefinedAsset`|`WPDefinedAsset[]` ([learn more](#wpdefinedasset))
Expand Down Expand Up @@ -625,7 +645,7 @@ In `block.json`:

### `WPDefinedAsset`

It extends `WPDefinedPath` for JavaScript and CSS files. An alternative to the file path would be a script or style handle name referencing an already registered asset using WordPress helpers.
It extends `WPDefinedPath` for JavaScript and CSS files. An alternative to the file path would be a script handle, script module ID, or style handle referencing an already registered asset using WordPress helpers.

**Example:**

Expand All @@ -635,21 +655,24 @@ In `block.json`:
{
"editorScript": "file:./index.js",
"script": "file:./script.js",
"viewScript": [ "file:./view.js", "example-shared-view-script" ],
"viewScriptModule": [
"file:./view.js",
"example-registered-script-module-id"
],
"editorStyle": "file:./index.css",
"style": [ "file:./style.css", "example-shared-style" ],
"viewStyle": [ "file:./view.css", "example-view-style" ]
}
```

In the context of WordPress, when a block is registered with PHP, it will automatically register all scripts and styles that are found in the `block.json` file and use file paths rather than asset handles.
In the context of WordPress, when a block is registered with PHP, it will automatically register all scripts, script modules, and styles that are found in the `block.json` file and use file paths rather than asset handles.

That's why, the `WPDefinedAsset` type has to offer a way to mirror also the shape of params necessary to register scripts and styles using [`wp_register_script`](https://developer.wordpress.org/reference/functions/wp_register_script/) and [`wp_register_style`](https://developer.wordpress.org/reference/functions/wp_register_style/), and then assign these as handles associated with your block using the `script`, `style`, `editor_script`, and `editor_style` block type registration settings.
That's why the `WPDefinedAsset` type has to offer a way to mirror the parameters necessary to register scripts, script modules, and styles using [`wp_register_script`](https://developer.wordpress.org/reference/functions/wp_register_script/), [`wp_register_script_module`](https://developer.wordpress.org/reference/functions/wp_register_script_module/), and [`wp_register_style`](https://developer.wordpress.org/reference/functions/wp_register_style/), and then assign these as handles or script module IDs associated with the block.

It's possible to provide an object which takes the following shape:

- `handle` (`string`) - the name of the script. If omitted, it will be auto-generated.
- `dependencies` (`string[]`) - an array of registered script handles this script depends on. Default value: `[]`.
- `dependencies` (`string[]`|`{ id: string, import?: 'dynamic'|'static' }[]`) - an array of registered script handles this script depends on. Script modules may use a simple string for static dependencies or the object form to indicate a dynamic dependency. Dynamic dependencies are dependencies that may or may not be used at runtime and are typically used with the dynamic `import('module-id')` syntax. Default value: `[]`.
- `version` (`string`|`false`|`null`) - string specifying the script version number, if it has one, which is added to the URL as a query string for cache busting purposes. If the version is set to `false`, a version number is automatically added equal to current installed WordPress version. If set to `null`, no version is added. Default value: `false`.

The definition is stored inside separate PHP file which ends with `.asset.php` and is located next to the JS/CSS file listed in `block.json`. WordPress will automatically detect this file through pattern matching. This option is the preferred one as it is expected it will become an option to auto-generate those asset files with `@wordpress/scripts` package.
Expand Down
45 changes: 31 additions & 14 deletions lib/experimental/script-modules.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
*/
function gutenberg_filter_block_type_metadata_settings_register_modules( $settings, $metadata = null ) {
$module_fields = array(
'viewModule' => 'view_module_ids',
// @todo remove viewModule support in Gutenberg >= 17.8 (replaced by viewScriptModule).
'viewModule' => 'view_script_module_ids',
'viewScriptModule' => 'view_script_module_ids',
);
foreach ( $module_fields as $metadata_field_name => $settings_field_name ) {
if ( ! empty( $settings[ $metadata_field_name ] ) ) {
Expand Down Expand Up @@ -49,19 +51,19 @@ function gutenberg_filter_block_type_metadata_settings_register_modules( $settin
* @param array $parsed_block The full block, including name and attributes.
* @param WP_Block $block_instance The block instance.
*/
function gutenberg_filter_render_block_enqueue_view_modules( $block_content, $parsed_block, $block_instance ) {
function gutenberg_filter_render_block_enqueue_view_script_modules( $block_content, $parsed_block, $block_instance ) {
$block_type = $block_instance->block_type;

if ( ! empty( $block_type->view_module_ids ) ) {
foreach ( $block_type->view_module_ids as $module_id ) {
if ( ! empty( $block_type->view_script_module_ids ) ) {
foreach ( $block_type->view_script_module_ids as $module_id ) {
wp_enqueue_script_module( $module_id );
}
}

return $block_content;
}

add_filter( 'render_block', 'gutenberg_filter_render_block_enqueue_view_modules', 10, 3 );
add_filter( 'render_block', 'gutenberg_filter_render_block_enqueue_view_script_modules', 10, 3 );

/**
* Finds a module ID for the selected block metadata field. It detects
Expand Down Expand Up @@ -159,7 +161,9 @@ function gutenberg_generate_block_asset_module_id( $block_name, $field_name, $in
}

$field_mappings = array(
'viewModule' => 'view-module',
// @todo remove viewModule support in Gutenberg >= 17.8 (replaced by viewScriptModule).
'viewModule' => 'view-script-module',
'viewScriptModule' => 'view-script-module',
);
$asset_handle = str_replace( '/', '-', $block_name ) .
'-' . $field_mappings[ $field_name ];
Expand All @@ -172,29 +176,42 @@ function gutenberg_generate_block_asset_module_id( $block_name, $field_name, $in
/**
* Registers a REST field for block types to provide view module IDs.
*
* Adds the `view_module_ids` field to block type objects in the REST API, which
* Adds the `view_script_module_ids` and `view_module_ids` (deprecated) field to block type objects in the REST API, which
* lists the script module IDs for any script modules associated with the
* block's viewModule(s) key.
*
* @since 6.5.0
* block's viewScriptModule key.
*/
function gutenberg_register_view_module_ids_rest_field() {
function gutenberg_register_view_script_module_ids_rest_field() {
// @todo remove view_module_ids support in Gutenberg >= 17.8 (replaced by view_script_module_ids).
register_rest_field(
'block-type',
'view_module_ids',
array(
'get_callback' => function ( $item ) {
$block_type = WP_Block_Type_Registry::get_instance()->get_registered( $item['name'] );
if ( isset( $block_type->view_module_ids ) ) {
return $block_type->view_module_ids;
if ( isset( $block_type->view_script_module_ids ) ) {
return $block_type->view_script_module_ids;
}
return array();
},
)
);

register_rest_field(
'block-type',
'view_script_module_ids',
array(
'get_callback' => function ( $item ) {
$block_type = WP_Block_Type_Registry::get_instance()->get_registered( $item['name'] );
if ( isset( $block_type->view_script_module_ids ) ) {
return $block_type->view_script_module_ids;
}
return array();
},
)
);
}

add_action( 'rest_api_init', 'gutenberg_register_view_module_ids_rest_field' );
add_action( 'rest_api_init', 'gutenberg_register_view_script_module_ids_rest_field' );

/**
* Registers the module if no module with that module identifier has already
Expand Down
Loading