Make WordPress Core

Opened 7 weeks ago

Closed 6 weeks ago

Last modified 4 weeks ago

#64150 closed defect (bug) (fixed)

Late-printed styles are not hoisted to HEAD if wp-block-library is not enqueued

Reported by: westonruter's profile westonruter Owned by: westonruter's profile westonruter
Milestone: 6.9 Priority: normal
Severity: normal Version: 6.9
Component: Script Loader Keywords: has-patch has-unit-tests
Focuses: performance Cc:

Description

This is a follow-up to #64099. In the PR, I raised a question for future investigation:

There's one gotcha here which I want to investigate in a follow-up. It could be that a site doesn't use blocks at all, and they have removed this hook:

add_action( 'wp_enqueue_scripts', 'wp_common_block_scripts_and_styles' );

In this case, the style won't be present to add a placeholder to. This is likely exceedingly rare and an edge case that I don't think blocks the initial merge of this. But I want to follow on testing on a sites using the Classic Editor exclusively.

Well, it wasn't so exceedingly rare, as @Soean reported this as a bug in 6.9-beta1:

we remove the wp-block-library styles from our site:

<?php
add_action(
        'enqueue_block_assets',
        function (): void {
                wp_deregister_style( 'wp-block-library' );
                wp_register_style( 'wp-block-library', '' );
        }
);

Like others:

With WP 6.9-Beta1 we don't get the global-styles-inline-css styles anymore, which breaks our styles.

To reproduce this issue, you can install the following plugin:

<?php
/**
 * Plugin Name: Enqueue Stylesheet at WP Footer
 */

add_action(
        'enqueue_block_assets',
        function (): void {
                wp_deregister_style( 'wp-block-library' );
        }
);

add_action(
        'wp_head',
        static function () {
                echo '<style>body { background-color: red; }</style>';
        }
);

add_action(
        'wp_footer',
        static function () {
                wp_enqueue_style( 'lime-background', plugin_dir_url( __FILE__ ) . 'lime-background.css' );
        }
);

The lime-background.css file contains simply:

body {
        background-color: lime !important;
}

When the plugin is active, a red background will appear because lime-background is printed at wp_footer with print_late_styles(), but since wp-block-library is not printed at wp_head, there is no placeholder comment in any the inline style for that stylesheet.

We can address this issue simply by falling back to appending the late-printed styles to the very end of the HEAD tag.

Change History (20)

This ticket was mentioned in PR #10417 on WordPress/wordpress-develop by @westonruter.


7 weeks ago
#1

  • Keywords has-patch has-unit-tests added

#3 @Soean
6 weeks ago

Hey,
now our page is rendered correct, but I see some new default block inline styles. We don't want to use these default styles.

This is because the should_load_separate_core_block_assets filter is set to true.

#4 @westonruter
6 weeks ago

@Soean Thanks for the feedback. Well, in that case I think you perhaps should just do:

<?php
add_filter( 'should_load_separate_core_block_assets', '__return_false' );

This will override what wp_load_classic_theme_block_styles_on_demand() does here:

<?php
add_filter( 'should_load_separate_core_block_assets', '__return_true', 0 );

#5 @Soean
6 weeks ago

I know this helps, but this means wp_load_classic_theme_block_styles_on_demand() will maybe break some other themes on the WP 6.9 update.

#6 @westonruter
6 weeks ago

@Soean What styles specifically are being included unwantedly? If they are specifically targeting blocks, and a site is not using blocks, then won't the styles just not apply to anything?

#7 @Soean
6 weeks ago

We use blocks and all our styles for the theme and content are in one file: style.css

When I look at the HTML source code now, I see that there are 862 new inline styles.

<style id='wp-block-heading-inline-css'>...</style>
<style id='wp-block-paragraph-inline-css'>...</style>
<style id='wp-block-button-inline-css'>...</style>
<style id='wp-block-button-inline-css'>...</style>
<style id='wp-block-buttons-inline-css'>...</style>
<style id='wp-block-cover-inline-css'>...</style>
<style id='wp-block-image-inline-css'>...</style>
<style id='wp-block-columns-inline-css'>...</style>
<style id='wp-block-group-inline-css'>...</style>

These styles increase the size of the document and are not cached like the style.css.

And some inline styles break our theme styles, like this one:

.wp-block-image.aligncenter, .wp-block-image.alignleft, .wp-block-image.alignright {
    display: table;
}

#8 @westonruter
6 weeks ago

@Soean Does your theme include add_theme_support( 'wp-block-styles' )?

#9 @Soean
6 weeks ago

No, the function wp_common_block_scripts_and_styles() enqueues wp-block-library on every theme. Regardless of the add_theme_support( 'wp-block-styles' )

https://developer.wordpress.org/reference/functions/wp_common_block_scripts_and_styles/

This is why so many themes use wp_deregister_style( 'wp-block-library' );

#10 @westonruter
6 weeks ago

@Soean Got it. OK, so what if we also modified wp_hoist_late_printed_styles() to only filter should_load_separate_core_block_assets and should_load_block_assets_on_demand to true if current_theme_supports( 'wp-block-styles' )? I just amended the PR with a commit to do that. If you could validate that it addresses your concerns and fixes the issue for you, that would be great.

#11 @Soean
6 weeks ago

@westonruter Thank you, this looks good to me. Now it works with our setup 🙂

#12 @westonruter
6 weeks ago

Excellent.

For reference, here is the plugin code I used to test this with a classic theme (e.g. Twenty Ten):

<?php
/**
 * Plugin Name: Disable Block Styles
 */

add_action(
        'enqueue_block_assets',
        function (): void {
                wp_deregister_style( 'wp-block-library' );
                wp_register_style( 'wp-block-library', '' );
        }
);

add_action(
        'after_setup_theme',
        static function (): void {
                remove_theme_support( 'wp-block-styles' );
        },
        PHP_INT_MAX
);

Without that commit, I see a lot of block-specific styles being enqueued. With the commit, they are excluded.

@peterwilsoncc commented on PR #10417:


6 weeks ago
#13

On this branch, I'm seeing the inline block styles loading when running the testing plugin included on the ticket.

Reproduction steps:

  1. Activate 2014
  2. Deactivate the test plugin
  3. Create a post with the gallery block or any other block that contains styles
  4. Activate the test plugin
  5. Check out the 6.8 branch (no need to npm install or rebuild assets)
  6. Load the post created earlier
  7. The gallery block will not be styled as there are are no block styles or inline CSS.
  8. Check out this branch
  9. Reload the post created earlier
  10. The gallery block will be styled as the inline block styles are included in the output

I'm figuring out a test for this, will follow up once I have one.

@westonruter commented on PR #10417:


6 weeks ago
#14

@peterwilsoncc as we've chatted about over Slack, the issue is there are two test plugins:

  1. Enqueue Stylesheet at WP Footer (as listed in the ticket description)
  2. Disable Block Styles (listed in comment)

To test the issue with a theme not wanting to have any block styles at all, the second plugin needs to be used to test. The first plugin is just to test that late-enqueued styles successfully get printed even when the wp-block-library is absent (and thus the normal placeholder in the inline style is not present, meaning a fallback to inserting the late-printed styles before </head> is needed.

@peterwilsoncc commented on PR #10417:


6 weeks ago
#15

As discussed in Slack, I think I was using the wrong plugin when testing earlier.

At the time of my earlier tests I was running the following, which produces different results on each branch.

add_action(
        'enqueue_block_assets',
        function (): void {
                wp_deregister_style( 'wp-block-library' );
        }
);

add_action(
        'wp_head',
        static function () {
                echo '<style>body { background-color: red; }</style>';
        }
);

add_action(
        'wp_footer',
        static function () {
                wp_register_style( 'lime-background', null );
                wp_add_inline_style( 'lime-background', 'body { background-color: lime !important; }' );
                wp_enqueue_style( 'lime-background' );
        }
);

Using the second plugin on the ticket I am seeing the same thing on both branches, IE running

add_action(
        'enqueue_block_assets',
        function (): void {
                wp_deregister_style( 'wp-block-library' );
                wp_register_style( 'wp-block-library', '' );
        }
);

add_action(
        'after_setup_theme',
        static function (): void {
                remove_theme_support( 'wp-block-styles' );
        },
        PHP_INT_MAX
);

So I think this is good to go.

#16 @westonruter
6 weeks ago

  • Resolution set to fixed
  • Status changed from assigned to closed

In 61076:

Script Loader: Fall back to hoisting late-printed styles to end of HEAD if wp-block-library is not enqueued.

When the wp-block-library stylesheet is not enqueued, there will be no associated inline style present. This inline style normally contains the placeholder CSS comment for the HTML Tag Processor to identify the token after which the late-printed styles should be inserted. However, when the wp-block-library stylesheet is not enqueued (such as in themes which do not use blocks), or else the inline style is not printed for whatever reason, this adds a fallback to insert the late-printed styles immediately before </head>. This ensures that late-printed styles will always get hoisted.

Developed in https://github.com/WordPress/wordpress-develop/pull/10417

Follow-up to [61008].

Props westonruter, peterwilsoncc, Soean.
See #64099, #43258.
Fixes #64150.

@westonruter commented on PR #10417:


6 weeks ago
#17

Committed in r61076.

#18 @westonruter
6 weeks ago

There's a complication to using current_theme_supports( 'wp-block-styles' ) as the signal for whether opt-in to loading separate block styles on demand. It doesn't work with Twenty Twenty, which is the only bundled theme which doesn't add this theme support.

We need to decouple wp-block-styles theme support from whether should_load_separate_core_block_assets and should_load_block_assets_on_demand are enabled. Enabling the latter should not cause any styles to be printed.

More: https://core.trac.wordpress.org/ticket/64166#comment:2

cc @Soean

#19 @westonruter
5 weeks ago

In 61122:

Script Loader: Load block styles on demand in classic themes even when wp-block-styles support is absent.

This reverts part of [61076] which made wp-block-styles theme support a precondition for opting in to should_load_separate_core_block_assets and should_load_block_assets_on_demand. This meant that the Twenty Twenty theme (and other themes without this support declared) would not benefit from on-demand block style loading. Nevertheless, even though such themes were not getting block styles loaded on demand, the wp_load_classic_theme_block_styles_on_demand() function was proceeding to opt in to the output buffer for hoisting late-printed styles, even though it was unlikely there would then be any. This meant the template enhancement output buffer was being opened for no reason.

Enabling on-demand block style loading is measured to improve FCP and LCP in Twenty Twenty, for example a ~13% improvement over a Fast 4G connection when loading the Sample Page.

Developed in https://github.com/WordPress/wordpress-develop/pull/10457

Follow-up to [61008], [61076], [60936].

Props westonruter.
See #64099, #64150, #64166, #43258.

#20 @westonruter
4 weeks ago

  • Focuses performance added
Note: See TracTickets for help on using tickets.