Skip to content

Script Loader: Fix missing block style loaded with style_handle#6628

Open
petitphp wants to merge 4 commits intoWordPress:trunkfrom
petitphp:ticket/55184
Open

Script Loader: Fix missing block style loaded with style_handle#6628
petitphp wants to merge 4 commits intoWordPress:trunkfrom
petitphp:ticket/55184

Conversation

@petitphp
Copy link

Fix missing block style loaded with style_handle.

It's possible to register a block style with a handle instead of an inline style. In that case and when wp_should_load_separate_core_block_assets() is true, the current code will rely on the render_block filter to detect if the block is used on the page and the block style need to be enqueued.

This doesn't work as expected, since the function is called in enqueue_block_assets after the render_block filter has run.

This PR add a new function hooked to wp_loaded to fix the issue.

Trac ticket: https://core.trac.wordpress.org/ticket/55184


This Pull Request is for code review only. Please keep all other discussion in the Trac ticket. Do not merge this Pull Request. See GitHub Pull Requests for Code Review in the Core Handbook for more details.

@github-actions
Copy link

github-actions bot commented May 24, 2024

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

Core Committers: Use this line as a base for the props when committing in SVN:

Props petitphp, mukesh27, wido, ktc_88, westonruter.

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

add_action( 'admin_enqueue_scripts', 'wp_common_block_scripts_and_styles' );
add_action( 'enqueue_block_assets', 'wp_enqueue_registered_block_scripts_and_styles' );
add_action( 'enqueue_block_assets', 'enqueue_block_styles_assets', 30 );
add_action( 'wp_loaded', 'enqueue_block_styles_handle_assets' );
Copy link
Member

Choose a reason for hiding this comment

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

Does this change will impact on performance?

Copy link
Author

Choose a reason for hiding this comment

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

Are we talking about server (PHP) or frontend (resources loading) performances ?

Copy link
Member

Choose a reason for hiding this comment

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

Frontend.

Copy link
Author

Choose a reason for hiding this comment

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

Currently, if a block style is register with a style_handle the CSS file is not included on the frontend. This PR fix that, so it's possible that it'll have an impact in terms of performance.

We could try and mitigate this by dynamically adding a path extra data to the dependency to let WordPress inline the style if it's below the threshold.

Co-authored-by: Mukesh Panchal <mukeshpanchal27@users.noreply.github.com>
@github-actions
Copy link

Test using WordPress Playground

The changes in this pull request can previewed and tested using a WordPress Playground instance.

WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser.

Some things to be aware of

  • The Plugin and Theme Directories cannot be accessed within Playground.
  • All changes will be lost when closing a tab with a Playground instance.
  • All changes will be lost when refreshing the page.
  • A fresh instance is created each time the link below is clicked.
  • Every time this pull request is updated, a new ZIP file containing all changes is created. If changes are not reflected in the Playground instance,
    it's possible that the most recent build failed, or has not completed. Check the list of workflow runs to be sure.

For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation.

Test this pull request with WordPress Playground.

Co-authored-by: Mukesh Panchal <mukeshpanchal27@users.noreply.github.com>
@kyle-charlton
Copy link

Is there any update on this?
I would love to see this fixed soon so I can start including my block style variations in their own stylesheets.

@westonruter
Copy link
Member

There are merge conflicts that need to be resolved and tests that need to be added. I haven't dug into the code yet to evaluate the approach.

@widoz
Copy link

widoz commented Feb 8, 2026

Hi there, I was testing this implementation and I think there's a small problem related to the fact that wp_loaded runs before wp_enqueue_scripts.

If I register a block style via the register_block_style I suppose I do that at init. For instance;

add_action('init', function () {
    register_block_style(
        'core/button',
        [
            'name' => $name,
            'label' => $label,
            'style_handle' => 'my-style-handle',
        ]
    );
});

The style handle imply I will take care of registering the style, which happen at wp_enqueue_scripts usually, but this action is performed after wp_loaded, hence, the following condition will always meet and the styles are not enqueued on the front end when

if ( 
    ! isset( $style_properties['style_handle'] ) || 
    ! isset( $wp_styles->registered[ $style_properties['style_handle'] ] ) 
) {
    continue;
}

A way to solve this problem is to register the style before wp_enqueue_scripts for instance at init but usually people would add those styles at the former, so it should be documented somewhere that, if you want to use a style handle you have to register its style at init.

Another option could be to register the style right away, if you want to pass an handle, you have to add a configuration permitting to call wp_register_style.

As an example, the style_handle could be of type string | array, we imply that if you pass a string you'll take care of registering the style at the right point in time, if you pass an array then, we know you want to let WordPress to register the style for you.

This approach will let consumers to integrate better with WordPress as the call to wp_register_style will check they are calling register_block_style at the right moment to register the style.

add_action('init', function () {
    register_block_style(
        'core/button',
        [
            'name' => $name,
            'label' => $label,
            'style_handle' => [
                'handle' => 'my-style-handle',
                // ... the other arguments for `wp_register_style`
            ]
        ]
    );
});
add_action( 'enqueue_block_assets', $enqueue_callback );
}
}
}
Copy link

Choose a reason for hiding this comment

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

I would like to suggest a possible different approach that not involve the creation of a buch of function stacks per block style.

The idea is to build a memoized map block_name => [ 'style_handle' ] that a single render_block or the enqueue_block_assets callback would loop to enqueue the block styles.

In a nutshell

add_action( 'wp_loaded', function () {
    global $wp_styles;

    $load_separate_block_assets = wp_should_load_separate_core_block_assets();
    $memoized_block_styles_handles = [];
    $block_styles = WP_Block_Styles_Registry::get_instance()->get_all_registered();

    foreach ( $block_styles as $block_name => $styles ) {
        foreach ( $styles as $style_properties ) {
            $style_handle = $style_properties['style_handle'];
            if ( ! isset( $style_handle ) || ! isset( $wp_styles->registered[ $style_handle ] ) ) {
                continue;
            }

            /*
             * Add the path to the CSS file in the style extra data if missing.
             *
             * This allows WordPress to inline the CSS instead of loading it like an external
             * resource if the file is below the size threshold.
             */
            $style = $wp_styles->registered[ $style_handle ];
            if ( $style && ! empty( $style->src ) && empty( $style->extra['path'] ) ) {
                $style_path = wp_normalize_path( str_replace( WP_CONTENT_URL, WP_CONTENT_DIR, $style->src ) );
                if ( is_readable( $style_path ) ) {
                    $style->add_data( 'path', $style_path );
                }
            }

            $memoized_block_styles_handles[$block_name][] = $style_properties['style_handle'];
        }
    }

    $block_names = array_keys( $memoized_block_styles_handles );
    $enqueue_callback = function() use ( $memoized_block_styles_handles ) {
        foreach ( $memoized_block_styles_handles as $block_styles_handles ) {
            foreach ( $block_styles_handles as $style_handle ) {
                wp_enqueue_style( $style_handle );
            }
        }
    };
    $render_block_callback = function ( $html, $block ) use ( $block_names, $enqueue_callback ) {
        if (in_array($block['blockName'], $block_names, true)) {
            $enqueue_callback();
        }

        return $html;
    };

    if ( $load_separate_block_assets ) {
        add_filter( 'render_block', $render_block_callback, 10, 2 );
        return;
    }

    add_action( 'enqueue_block_assets', $enqueue_callback);
} );
@westonruter
Copy link
Member

This PR is almost 2-years stale now and there are merge conflicts. Either it should be closed in favor of a new PR, or the merge conflicts need to be resolved.

Comment on lines 2665 to 2683
Copy link
Member

@westonruter westonruter Feb 12, 2026

Choose a reason for hiding this comment

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

Should this be left as-is but then just to modify the condition to skip the logic if the style was already enqueued?

- if ( isset( $style_properties['style_handle'] ) ) {
+ if ( isset( $style_properties['style_handle'] ) && ! wp_style_is( $style_properties['style_handle'] ) ) {
Comment on lines +2703 to +2715
/*
* Add the path to the CSS file in the style extra data if missing.
*
* This allow WordPress to inline the CSS instead of loading it like an external resource if the file
* is bellow the size threshold.
*/
$style = $wp_styles->registered[ $style_properties['style_handle'] ];
if ( $style && ! empty( $style->src ) && empty( $style->extra['path'] ) ) {
$style_path = wp_normalize_path( str_replace( WP_CONTENT_URL, WP_CONTENT_DIR, $style->src ) );
if ( is_readable( $style_path ) ) {
$style->add_data( 'path', $style_path );
}
}
Copy link
Member

Choose a reason for hiding this comment

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

Note: Similar logic exists in wp_enqueue_block_style() and in register_core_block_style_handles(). The register_core_block_style_handles() function is already running at init, but it short-circuits when wp_should_load_separate_core_block_assets() returns false. Prior to 6.9, the wp_should_load_separate_core_block_assets() function would return false by default for classic themes, but as of Core-64099 separate block styles are now loaded on demand by default.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

5 participants