From 30d6172eed95667020e7de6c29f6997e1e50e2a3 Mon Sep 17 00:00:00 2001 From: Jonny Harris Date: Tue, 27 Jun 2023 11:26:12 +0000 Subject: [PATCH] Script Loader: Fix performance issues in `wp_common_block_scripts_and_styles`. In [52069] the function `wp_common_block_scripts_and_styles` was changed load individual theme stylesheets, if the current theme supports block styles and loading separate core block assets. To do this, the function calls many expensive file operation functions, such as `glob`, `file_exists` and `file_get_contents`. This is wasteful, as these functions are loaded on every page request, even request that do not include blocks, like REST API calls. In [56044] all core block styles are registered in a single place. In `register_core_block_style_handles` calls `glob` to get all css styles in block directories. While registering style and editor styles, also register block theme styles, under a new style handle. Example `wp-block-avatar-theme`. If the current theme supports block styles, also request the block to enqueue the theme style on the front end. As these new stylesheets have a path attribute set, the function `wp_maybe_inline_styles` will automatically inline the styles for you. Props spacedmonkey, flixos90, oandregal, costdev, audrasjb, mukesh27. Fixes #58560. git-svn-id: https://develop.svn.wordpress.org/trunk@56064 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-includes/blocks.php | 4 ++ src/wp-includes/blocks/index.php | 48 +++++++++++-------- src/wp-includes/script-loader.php | 16 +------ .../blocks/registerCoreBlockStyleHandles.php | 32 +++++++++++++ 4 files changed, 65 insertions(+), 35 deletions(-) diff --git a/src/wp-includes/blocks.php b/src/wp-includes/blocks.php index 5fa7f1d6d0..aebb4b4065 100644 --- a/src/wp-includes/blocks.php +++ b/src/wp-includes/blocks.php @@ -373,6 +373,10 @@ function register_block_type_from_metadata( $file_or_folder, $args = array() ) { if ( ! isset( $metadata['style'] ) ) { $metadata['style'] = "wp-block-$block_name"; } + if ( current_theme_supports( 'wp-block-styles' ) && wp_should_load_separate_core_block_assets() ) { + $metadata['style'] = (array) $metadata['style']; + $metadata['style'][] = "wp-block-{$block_name}-theme"; + } if ( ! isset( $metadata['editorStyle'] ) ) { $metadata['editorStyle'] = "wp-block-{$block_name}-editor"; } diff --git a/src/wp-includes/blocks/index.php b/src/wp-includes/blocks/index.php index 51cf0c91e8..f9ffa411af 100644 --- a/src/wp-includes/blocks/index.php +++ b/src/wp-includes/blocks/index.php @@ -55,6 +55,29 @@ function register_core_block_style_handles() { $files = glob( __DIR__ . '/**/**.css' ); } + $register_style = static function( $name, $filename, $style_handle ) use ( $includes_path, $includes_url, $suffix, $wp_styles, $files ) { + $style_path = "blocks/{$name}/{$filename}{$suffix}.css"; + $path = $includes_path . $style_path; + + if ( ! in_array( $path, $files, true ) ) { + $wp_styles->add( + $style_handle, + false + ); + return; + } + + $wp_styles->add( $style_handle, $includes_url . $style_path ); + $wp_styles->add_data( $style_handle, 'path', $path ); + + $rtl_file = str_replace( "{$suffix}.css", "-rtl{$suffix}.css", $path ); + if ( is_rtl() && in_array( $rtl_file, $files, true ) ) { + $wp_styles->add_data( $style_handle, 'rtl', 'replace' ); + $wp_styles->add_data( $style_handle, 'suffix', $suffix ); + $wp_styles->add_data( $style_handle, 'path', $rtl_file ); + } + }; + foreach ( $core_blocks_meta as $name => $schema ) { /** This filter is documented in wp-includes/blocks.php */ $schema = apply_filters( 'block_type_metadata', $schema ); @@ -67,32 +90,15 @@ function register_core_block_style_handles() { $schema['editorStyle'] = "wp-block-{$name}-editor"; } + // Register block theme styles. + $register_style( $name, 'theme', "wp-block-{$name}-theme" ); + foreach ( $style_fields as $style_field => $filename ) { $style_handle = $schema[ $style_field ]; if ( is_array( $style_handle ) ) { continue; } - - $style_path = "blocks/{$name}/{$filename}{$suffix}.css"; - $path = $includes_path . $style_path; - - if ( ! in_array( $path, $files, true ) ) { - $wp_styles->add( - $style_handle, - false - ); - continue; - } - - $wp_styles->add( $style_handle, $includes_url . $style_path ); - $wp_styles->add_data( $style_handle, 'path', $path ); - - $rtl_file = str_replace( "{$suffix}.css", "-rtl{$suffix}.css", $path ); - if ( is_rtl() && in_array( $rtl_file, $files, true ) ) { - $wp_styles->add_data( $style_handle, 'rtl', 'replace' ); - $wp_styles->add_data( $style_handle, 'suffix', $suffix ); - $wp_styles->add_data( $style_handle, 'path', $rtl_file ); - } + $register_style( $name, $filename, $style_handle ); } } } diff --git a/src/wp-includes/script-loader.php b/src/wp-includes/script-loader.php index 8d9b54eb43..b6414350b7 100644 --- a/src/wp-includes/script-loader.php +++ b/src/wp-includes/script-loader.php @@ -2372,20 +2372,8 @@ function wp_common_block_scripts_and_styles() { wp_enqueue_style( 'wp-block-library' ); - if ( current_theme_supports( 'wp-block-styles' ) ) { - if ( wp_should_load_separate_core_block_assets() ) { - $suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? 'css' : 'min.css'; - $files = glob( __DIR__ . "/blocks/**/theme.$suffix" ); - foreach ( $files as $path ) { - $block_name = basename( dirname( $path ) ); - if ( is_rtl() && file_exists( __DIR__ . "/blocks/$block_name/theme-rtl.$suffix" ) ) { - $path = __DIR__ . "/blocks/$block_name/theme-rtl.$suffix"; - } - wp_add_inline_style( "wp-block-{$block_name}", file_get_contents( $path ) ); - } - } else { - wp_enqueue_style( 'wp-block-library-theme' ); - } + if ( current_theme_supports( 'wp-block-styles' ) && ! wp_should_load_separate_core_block_assets() ) { + wp_enqueue_style( 'wp-block-library-theme' ); } /** diff --git a/tests/phpunit/tests/blocks/registerCoreBlockStyleHandles.php b/tests/phpunit/tests/blocks/registerCoreBlockStyleHandles.php index 75c05f8f59..a4ed1dd418 100644 --- a/tests/phpunit/tests/blocks/registerCoreBlockStyleHandles.php +++ b/tests/phpunit/tests/blocks/registerCoreBlockStyleHandles.php @@ -55,6 +55,9 @@ class Tests_Blocks_registerCoreBlockStyleHandles extends WP_UnitTestCase { * @ticket 58528 * * @dataProvider data_block_data + * + * @param string $name The block name. + * @param array $schema The block's schema. */ public function test_wp_should_load_separate_core_block_assets_false( $name, $schema ) { register_core_block_style_handles(); @@ -74,6 +77,9 @@ class Tests_Blocks_registerCoreBlockStyleHandles extends WP_UnitTestCase { * @ticket 58528 * * @dataProvider data_block_data + * + * @param string $name The block name. + * @param array $schema The block's schema. */ public function test_wp_should_load_separate_core_block_assets_true( $name, $schema ) { add_filter( 'should_load_separate_core_block_assets', '__return_true' ); @@ -99,6 +105,32 @@ class Tests_Blocks_registerCoreBlockStyleHandles extends WP_UnitTestCase { } } + /** + * @ticket 58560 + * + * @dataProvider data_block_data + * + * @param string $name The block name. + */ + public function test_wp_should_load_separate_core_block_assets_current_theme_supports( $name ) { + add_filter( 'should_load_separate_core_block_assets', '__return_true' ); + add_theme_support( 'wp-block-styles' ); + register_core_block_style_handles(); + + $wp_styles = $GLOBALS['wp_styles']; + + $style_handle = "wp-block-{$name}-theme"; + + $this->assertArrayHasKey( $style_handle, $wp_styles->registered, 'The key should exist, as this style should be registered' ); + if ( false === $wp_styles->registered[ $style_handle ]->src ) { + $this->assertEmpty( $wp_styles->registered[ $style_handle ]->extra, 'If source is false, not style path should be set' ); + } else { + $this->assertStringContainsString( $this->includes_url, $wp_styles->registered[ $style_handle ]->src, 'Source of style should contain the includes url' ); + $this->assertNotEmpty( $wp_styles->registered[ $style_handle ]->extra, 'The path of the style should exist' ); + $this->assertArrayHasKey( 'path', $wp_styles->registered[ $style_handle ]->extra, 'The path key of the style should exist in extra array' ); + $this->assertNotEmpty( $wp_styles->registered[ $style_handle ]->extra['path'], 'The path key of the style should not be empty' ); + } + } public function data_block_data() { $core_blocks_meta = require ABSPATH . WPINC . '/blocks/blocks-json.php';