Skip to content

Commit

Permalink
Script Modules: Centralize registration (#65460)
Browse files Browse the repository at this point in the history
Rework how Script Modules are registered in Gutenberg.

Script Module registration is handled in one central place.

A combined assets file is used for Script Modules and registration. This
means that dependencies and versions will be used correctly and kept
up-to-date while avoiding repeated file reads.

Block library Script Module assets that are enqueued on demand _are
registered in a centralized location_. The assets are enqueued on
demand. **This requires a Core change** since the block library PHP
files are synced to Core and also require centralized Script Module
registration (WordPress/wordpress-develop#7360).

This solves a problem where Gutenberg-specific code was being shipped in
Core through block-library.

The block library Script Module asset Module IDs are renamed to indicate
they are view files and align with the naming from #65064:
@wordpress/block-library/query is @wordpress/block-library/query/view
(indicating it is a view file).

---

This is sufficient to change Script Modules to use Gutenberg in a
backwards compatible way:

- `@wordpress/ineractivity` and `@wordpress/interactivity-router` were
  registered on `wp_enqueue_scripts`. That action fires after the
  `wp_default_scripts` used here. Registering an already registered
  Script Module is a no-op. This change registers first.
- The only other Script Modules currently available in Core are from the
  block library. Those have been registered conditionally on use. The ID
  is changed here, so there's little risk of the wrong version being
  used.

There is a Core companion PR that will be necessary to land:
WordPress/wordpress-develop#7360

---

Co-authored-by: sirreal <[email protected]>
Co-authored-by: gziolo <[email protected]>
  • Loading branch information
3 people authored Sep 20, 2024
1 parent ff112d7 commit 2632234
Show file tree
Hide file tree
Showing 11 changed files with 72 additions and 129 deletions.
5 changes: 3 additions & 2 deletions .github/workflows/unit-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,9 @@ jobs:
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
with:
name: build-assets
path: ./build/
path: |
./build/
./build-module/
test-php:
name: PHP ${{ matrix.php }}${{ matrix.multisite && ' multisite' || '' }}${{ matrix.wordpress != '' && format( ' (WP {0}) ', matrix.wordpress ) || '' }} on ubuntu-latest
Expand Down Expand Up @@ -212,7 +214,6 @@ jobs:
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
with:
name: build-assets
path: ./build

- name: Docker debug information
run: |
Expand Down
3 changes: 3 additions & 0 deletions backport-changelog/6.7/7360.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
https://github.com/WordPress/wordpress-develop/pull/7360

* https://github.com/WordPress/gutenberg/pull/65460
50 changes: 50 additions & 0 deletions lib/client-assets.php
Original file line number Diff line number Diff line change
Expand Up @@ -601,6 +601,56 @@ function gutenberg_register_vendor_scripts( $scripts ) {
}
add_action( 'wp_default_scripts', 'gutenberg_register_vendor_scripts' );

/**
* Registers or re-registers Gutenberg Script Modules.
*
* Script modules that are registered by Core will be re-registered by Gutenberg.
*
* @since 19.3.0
*/
function gutenberg_default_script_modules() {
/*
* Expects multidimensional array like:
*
* 'interactivity/index.min.js' => array('dependencies' => array(…), 'version' => '…'),
* 'interactivity/debug.min.js' => array('dependencies' => array(…), 'version' => '…'),
* 'interactivity-router/index.min.js' => …
*/
$assets = include gutenberg_dir_path() . '/build-module/assets.php';

foreach ( $assets as $file_name => $script_module_data ) {
/*
* Build the WordPress Script Module ID from the file name.
* Prepend `@wordpress/` and remove extensions and `/index` if present:
* - interactivity/index.min.js => @wordpress/interactivity
* - interactivity/debug.min.js => @wordpress/interactivity/debug
* - block-library/query/view.js => @wordpress/block-library/query/view
*/
$script_module_id = '@wordpress/' . preg_replace( '~(?:/index)?\.min\.js$~D', '', $file_name, 1 );
switch ( $script_module_id ) {
/*
* Interactivity exposes two entrypoints, "/index" and "/debug".
* "/debug" should replalce "/index" in devlopment.
*/
case '@wordpress/interactivity/debug':
if ( ! SCRIPT_DEBUG ) {
continue 2;
}
$script_module_id = '@wordpress/interactivity';
break;
case '@wordpress/interactivity':
if ( SCRIPT_DEBUG ) {
continue 2;
}
break;
}

$path = gutenberg_url( "build-module/{$file_name}" );
wp_register_script_module( $script_module_id, $path, $script_module_data['dependencies'], $script_module_data['version'] );
}
}
remove_action( 'wp_default_scripts', 'wp_default_script_modules' );
add_action( 'wp_default_scripts', 'gutenberg_default_script_modules' );

/*
* Always remove the Core action hook while gutenberg_enqueue_stored_styles() exists to avoid styles being printed twice.
Expand Down
25 changes: 2 additions & 23 deletions lib/experimental/script-modules.php
Original file line number Diff line number Diff line change
Expand Up @@ -239,26 +239,5 @@ function gutenberg_a11y_script_module_html() {
. '<div id="a11y-speak-polite" class="a11y-speak-region" aria-live="polite" aria-relevant="additions text" aria-atomic="true"></div>'
. '</div>';
}

/**
* Registers Gutenberg Script Modules.
*
* @since 19.3
*/
function gutenberg_register_script_modules() {
// When in production, use the plugin's version as the default asset version;
// else (for development or test) default to use the current time.
$default_version = defined( 'GUTENBERG_VERSION' ) && ! SCRIPT_DEBUG ? GUTENBERG_VERSION : time();

wp_deregister_script_module( '@wordpress/a11y' );
wp_register_script_module(
'@wordpress/a11y',
gutenberg_url( 'build-module/a11y/index.min.js' ),
array(),
$default_version
);

add_action( 'wp_footer', 'gutenberg_a11y_script_module_html' );
add_action( 'admin_footer', 'gutenberg_a11y_script_module_html' );
}
add_action( 'init', 'gutenberg_register_script_modules' );
add_action( 'wp_footer', 'gutenberg_a11y_script_module_html' );
add_action( 'admin_footer', 'gutenberg_a11y_script_module_html' );
31 changes: 0 additions & 31 deletions lib/interactivity-api.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,37 +5,6 @@
* @package gutenberg
*/

/**
* Deregisters the Core Interactivity API Modules and replace them
* with the ones from the Gutenberg plugin.
*/
function gutenberg_reregister_interactivity_script_modules() {
$default_version = defined( 'GUTENBERG_VERSION' ) && ! SCRIPT_DEBUG ? GUTENBERG_VERSION : time();
wp_deregister_script_module( '@wordpress/interactivity' );
wp_deregister_script_module( '@wordpress/interactivity-router' );

wp_register_script_module(
'@wordpress/interactivity',
gutenberg_url( '/build-module/' . ( SCRIPT_DEBUG ? 'interactivity/debug.min.js' : 'interactivity/index.min.js' ) ),
array(),
$default_version
);

wp_register_script_module(
'@wordpress/interactivity-router',
gutenberg_url( '/build-module/interactivity-router/index.min.js' ),
array(
array(
'id' => '@wordpress/a11y',
'import' => 'dynamic',
),
'@wordpress/interactivity',
),
$default_version
);
}
add_action( 'init', 'gutenberg_reregister_interactivity_script_modules' );

/**
* Adds script data to the interactivity-router script module.
*
Expand Down
13 changes: 1 addition & 12 deletions packages/block-library/src/file/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,7 @@
function render_block_core_file( $attributes, $content ) {
// If it's interactive, enqueue the script module and add the directives.
if ( ! empty( $attributes['displayPreview'] ) ) {
$suffix = wp_scripts_get_suffix();
if ( defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN ) {
$module_url = gutenberg_url( '/build-module/block-library/file/view.min.js' );
}

wp_register_script_module(
'@wordpress/block-library/file',
isset( $module_url ) ? $module_url : includes_url( "blocks/file/view{$suffix}.js" ),
array( '@wordpress/interactivity' ),
defined( 'GUTENBERG_VERSION' ) ? GUTENBERG_VERSION : get_bloginfo( 'version' )
);
wp_enqueue_script_module( '@wordpress/block-library/file' );
wp_enqueue_script_module( '@wordpress/block-library/file/view' );

$processor = new WP_HTML_Tag_Processor( $content );
$processor->next_tag();
Expand Down
14 changes: 1 addition & 13 deletions packages/block-library/src/image/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,19 +70,7 @@ function render_block_core_image( $attributes, $content, $block ) {
isset( $lightbox_settings['enabled'] ) &&
true === $lightbox_settings['enabled']
) {
$suffix = wp_scripts_get_suffix();
if ( defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN ) {
$module_url = gutenberg_url( '/build-module/block-library/image/view.min.js' );
}

wp_register_script_module(
'@wordpress/block-library/image',
isset( $module_url ) ? $module_url : includes_url( "blocks/image/view{$suffix}.js" ),
array( '@wordpress/interactivity' ),
defined( 'GUTENBERG_VERSION' ) ? GUTENBERG_VERSION : get_bloginfo( 'version' )
);

wp_enqueue_script_module( '@wordpress/block-library/image' );
wp_enqueue_script_module( '@wordpress/block-library/image/view' );

/*
* This render needs to happen in a filter with priority 15 to ensure that
Expand Down
13 changes: 1 addition & 12 deletions packages/block-library/src/navigation/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -622,18 +622,7 @@ private static function get_nav_element_directives( $is_interactive ) {
*/
private static function handle_view_script_module_loading( $attributes, $block, $inner_blocks ) {
if ( static::is_interactive( $attributes, $inner_blocks ) ) {
$suffix = wp_scripts_get_suffix();
if ( defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN ) {
$module_url = gutenberg_url( '/build-module/block-library/navigation/view.min.js' );
}

wp_register_script_module(
'@wordpress/block-library/navigation',
isset( $module_url ) ? $module_url : includes_url( "blocks/navigation/view{$suffix}.js" ),
array( '@wordpress/interactivity' ),
defined( 'GUTENBERG_VERSION' ) ? GUTENBERG_VERSION : get_bloginfo( 'version' )
);
wp_enqueue_script_module( '@wordpress/block-library/navigation' );
wp_enqueue_script_module( '@wordpress/block-library/navigation/view' );
}
}

Expand Down
22 changes: 1 addition & 21 deletions packages/block-library/src/query/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,27 +24,7 @@ function render_block_core_query( $attributes, $content, $block ) {
// Enqueue the script module and add the necessary directives if the block is
// interactive.
if ( $is_interactive ) {
$suffix = wp_scripts_get_suffix();
if ( defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN ) {
$module_url = gutenberg_url( '/build-module/block-library/query/view.min.js' );
}

wp_register_script_module(
'@wordpress/block-library/query',
isset( $module_url ) ? $module_url : includes_url( "blocks/query/view{$suffix}.js" ),
array(
array(
'id' => '@wordpress/interactivity',
'import' => 'static',
),
array(
'id' => '@wordpress/interactivity-router',
'import' => 'dynamic',
),
),
defined( 'GUTENBERG_VERSION' ) ? GUTENBERG_VERSION : get_bloginfo( 'version' )
);
wp_enqueue_script_module( '@wordpress/block-library/query' );
wp_enqueue_script_module( '@wordpress/block-library/query/view' );

$p = new WP_HTML_Tag_Processor( $content );
if ( $p->next_tag() ) {
Expand Down
13 changes: 1 addition & 12 deletions packages/block-library/src/search/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,18 +80,7 @@ function render_block_core_search( $attributes ) {
// If it's interactive, enqueue the script module and add the directives.
$is_expandable_searchfield = 'button-only' === $button_position;
if ( $is_expandable_searchfield ) {
$suffix = wp_scripts_get_suffix();
if ( defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN ) {
$module_url = gutenberg_url( '/build-module/block-library/search/view.min.js' );
}

wp_register_script_module(
'@wordpress/block-library/search',
isset( $module_url ) ? $module_url : includes_url( "blocks/search/view{$suffix}.js" ),
array( '@wordpress/interactivity' ),
defined( 'GUTENBERG_VERSION' ) ? GUTENBERG_VERSION : get_bloginfo( 'version' )
);
wp_enqueue_script_module( '@wordpress/block-library/search' );
wp_enqueue_script_module( '@wordpress/block-library/search/view' );

$input->set_attribute( 'data-wp-bind--aria-hidden', '!context.isSearchInputVisible' );
$input->set_attribute( 'data-wp-bind--tabindex', 'state.tabindex' );
Expand Down
12 changes: 9 additions & 3 deletions tools/webpack/script-modules.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,11 @@ module.exports = {
},
output: {
devtoolNamespace: 'wp',
filename: './build-module/[name].min.js',
filename: '[name].min.js',
library: {
type: 'module',
},
path: join( __dirname, '..', '..' ),
path: join( __dirname, '..', '..', 'build-module' ),
environment: { module: true },
module: true,
chunkFormat: 'module',
Expand All @@ -102,7 +102,13 @@ module.exports = {
resolve: {
extensions: [ '.js', '.ts', '.tsx' ],
},
plugins: [ ...plugins, new DependencyExtractionWebpackPlugin() ],
plugins: [
...plugins,
new DependencyExtractionWebpackPlugin( {
combineAssets: true,
combinedOutputFile: `./assets.php`,
} ),
],
watchOptions: {
ignored: [ '**/node_modules' ],
aggregateTimeout: 500,
Expand Down

0 comments on commit 2632234

Please sign in to comment.