-
Notifications
You must be signed in to change notification settings - Fork 3.2k
#64099: Improve hoisted stylesheet ordering #10436
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
#64099: Improve hoisted stylesheet ordering #10436
Conversation
…ideClass suppression for PHPCS See WordPress#10288 (comment)
…sideClass in script-loader.php
Test using WordPress PlaygroundThe 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
For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation. |
| $instance->set_bookmark( 'here' ); | ||
| return $instance->bookmarks['here']; | ||
| $this->set_bookmark( 'here' ); | ||
| return $this->bookmarks['here']; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so much better with the removal of the additional surprising complexity!
tests/phpunit/tests/template.php
Outdated
| } | ||
|
|
||
| /** | ||
| * Export PHP array as string formatted for pasting into unit test case. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a brief example would go a long way. I have a rough idea of what this is supposed to do, which I assume is to aid in debugging test failures, but I really can’t visualize it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added in 156c6f5
tests/phpunit/tests/template.php
Outdated
| $export = preg_replace( '/\barray \($/m', 'array(', $export ); | ||
| if ( isset( $snapshot[0] ) ) { | ||
| $export = preg_replace( '/^(\s+)\d+\s+=>\s+/m', '$1', $export ); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we’re trying to remove numeric indices?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, unfortunately var_export() includes them, even when sequential and starting from 0.
…into trac-64099-improve-hoisted-stylesheet-ordering
…into trac-64099-improve-hoisted-stylesheet-ordering
Co-authored-by: Dennis Snell <[email protected]>
…parate_core_block_assets was disabled
| function ( $buffer ) use ( $placeholder, &$printed_block_styles, &$printed_late_styles ) { | ||
|
|
||
| // Anonymous subclass of WP_HTML_Tag_Processor which exposes underlying bookmark spans. | ||
| $processor = new class( $buffer ) extends WP_HTML_Tag_Processor { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dmsnell How does this updated WP_HTML_Tag_Processor extension look here? Note the insert_before and insert_after methods.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And now a review method as well.
…into trac-64099-improve-hoisted-stylesheet-ordering
2b38a00 to
1895883
Compare
1895883 to
fd0c402
Compare
dd0ce41 to
c2fd29f
Compare
|
This was a big headache. But I believe all the kinks are now worked out! |
|
I've tested this with a helper plugin that includes There's various ways a theme may wish to modify the block styles that are now being replaced with Core's styles.
|
…into trac-64099-improve-hoisted-stylesheet-ordering
…le is printed and ensure it is added just in time
|
@peterwilsoncc Thank you for this. After evaluating the error scenarios, they all appear to be the same as is described in my ticket comment. Namely, if a site is explicitly expecting add_filter( 'should_load_separate_core_block_assets', '__return_false' );This needs to be called out in the dev note for sure. |
…into trac-64099-improve-hoisted-stylesheet-ordering
Reverts part of 9f816a3 It turns out the depenency src is empty when a build hasn't been done
peterwilsoncc
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good for commit.
I've gone through manual testing and reviewed the code in the editor as the diff is a little less clear than reading the code.
As discussed here and in slack, I think we'll need to shout out classic themes replacing styles in the dev note to ensure they are using the correct filters.
Hitting approve as the tests look firmly on their way to passing.
…) to preserve CSS cascade. This ensures that on-demand block styles are inserted right after the `wp-block-library` inline style whereas other stylesheets not related to blocks are appended to the end of the `HEAD`. This helps ensure the expected cascade is preserved. If no `wp-block-library` inline style is present, then all styles get appended to the `HEAD` regardless. The handling of the CSS placeholder comment added to the `wp-block-library` inline style is also improved. It is now inserted later to ensure the inline style is printed. Additionally, when the CSS placeholder comment is removed from the `wp-block-library` inline style, the entire `STYLE` tag is now removed if there are no styles left (aside from the `sourceURL` comment). Lastly, the use of the HTML Tag Processor is significantly improved to leverage `WP_HTML_Text_Replacement`. Developed in #10436 Follow-up to [61008]. Props westonruter, peterwilsoncc, dmsnell. Fixes #64099. git-svn-id: https://develop.svn.wordpress.org/trunk@61174 602fd350-edb4-49c9-b593-d223f7449a82
…) to preserve CSS cascade. This ensures that on-demand block styles are inserted right after the `wp-block-library` inline style whereas other stylesheets not related to blocks are appended to the end of the `HEAD`. This helps ensure the expected cascade is preserved. If no `wp-block-library` inline style is present, then all styles get appended to the `HEAD` regardless. The handling of the CSS placeholder comment added to the `wp-block-library` inline style is also improved. It is now inserted later to ensure the inline style is printed. Additionally, when the CSS placeholder comment is removed from the `wp-block-library` inline style, the entire `STYLE` tag is now removed if there are no styles left (aside from the `sourceURL` comment). Lastly, the use of the HTML Tag Processor is significantly improved to leverage `WP_HTML_Text_Replacement`. Developed in WordPress/wordpress-develop#10436 Follow-up to [61008]. Props westonruter, peterwilsoncc, dmsnell. Fixes #64099. Built from https://develop.svn.wordpress.org/trunk@61174 git-svn-id: http://core.svn.wordpress.org/trunk@60510 1a063a9b-81f0-0310-95a4-ce76da25c4cd
…) to preserve CSS cascade. This ensures that on-demand block styles are inserted right after the `wp-block-library` inline style whereas other stylesheets not related to blocks are appended to the end of the `HEAD`. This helps ensure the expected cascade is preserved. If no `wp-block-library` inline style is present, then all styles get appended to the `HEAD` regardless. The handling of the CSS placeholder comment added to the `wp-block-library` inline style is also improved. It is now inserted later to ensure the inline style is printed. Additionally, when the CSS placeholder comment is removed from the `wp-block-library` inline style, the entire `STYLE` tag is now removed if there are no styles left (aside from the `sourceURL` comment). Lastly, the use of the HTML Tag Processor is significantly improved to leverage `WP_HTML_Text_Replacement`. Developed in WordPress/wordpress-develop#10436 Follow-up to [61008]. Props westonruter, peterwilsoncc, dmsnell. Fixes #64099. Built from https://develop.svn.wordpress.org/trunk@61174 git-svn-id: https://core.svn.wordpress.org/trunk@60510 1a063a9b-81f0-0310-95a4-ce76da25c4cd
dmsnell
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@westonruter the HTML API usage looks nice. adding those extra methods to the anonymous class does clean up the logic in the part handling the STYLE placeholders.
| */ | ||
| private function get_span(): WP_HTML_Span { | ||
| // Note: This call will never fail according to the usage of this class, given it is always called after ::next_tag() is true. | ||
| $this->set_bookmark( 'here' ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
technically it could also fail if there are too many bookmarks already. probably not an issue. in my own code I haven’t been documenting these cases of overlooking the failure given I control the whole flow of execution in the anonymous classes.








This primarily ensures that stylesheets related to blocks are inserted right after
wp-block-librarywhereas other stylesheets not related to blocks are appended to the end of theHEAD. This helps ensure the expected cascade is preserved. If nowp-block-libraryinline style is present, then all styles get appended to theHEADregardless.When the CSS placeholder comment is removed from the
wp-block-libraryinline style, the entire inline style is now removed if there are no styles left (aside from thesourceURLcomment).This PR also addresses various deficiencies with the logic in
wp_load_classic_theme_block_styles_on_demand()andwp_hoist_late_printed_styles()after more thorough review.Lastly, the use of the HTML Tag Processor was significantly improved to leverage
WP_HTML_Text_Replacement.Trac ticket: https://core.trac.wordpress.org/ticket/64099
This is a follow-up to #10288 (r61008) and to @dmsnell's post-merge feedback.
Gemini Review
The changes introduce a new mechanism for hoisting late-printed styles, particularly block-related styles, to the
<head>section in classic themes. This is a significant improvement for performance and proper CSS cascade.Here's a detailed review:
phpcompat.xml.distPHPCompatibility.FunctionDeclarations.NewClosure.ThisFoundOutsideClasshas been added for/src/wp-includes/script-loader.php.thisoutside a class context has been introduced. The comment correctly notes this is a temporary exclusion pending PHPCompatibility v10. This is acceptable as a temporary measure, but it's important to follow up and remove this exclusion once the compatibility issue is resolved.src/wp-includes/script-loader.phpwp_print_head_scripts():wp_hoist_late_printed_styles()functions, detailing the two sets of styles (block-related and others) and their hoisting.wp_load_classic_theme_block_styles_on_demand():if ( ! wp_should_load_separate_core_block_assets() ) { return; }has been added. Theprint_late_stylesfilter and its associated comment have been removed.print_late_stylesfilter suggests a more streamlined approach to handling late styles, which is positive.wp_hoist_late_printed_styles():capture_late_stylesclosure now captures both$printed_block_stylesand$printed_late_styles. Logic has been added to differentiate and gather block-related styles.print_late_styles()is replaced bywp_styles()->do_footer_items(). The anonymousWP_HTML_Tag_Processorclass has new utility methods (get_span,insert_before,insert_after,remove). The style insertion logic within thewp_template_enhancement_output_bufferfilter has been significantly refactored to precisely insert block styles afterwp-block-library-inline-cssand other late styles before</head>. It also handles the removal of empty inline style tags.WP_HTML_Tag_Processorfor precise HTML manipulation is a robust approach. The logic for removing empty inline style tags (especially those only containing asourceURLcomment) is a good detail.preg_match( ':^/\*# sourceURL=\\S+? \*/$:', trim( $css_text ) )is quite specific. A brief comment explaining its purpose (to identify an inline style that is effectively empty, containing only a sourceURL comment) would enhance readability.tests/phpunit/tests/template.phpsetUp()andtearDown():wp_scripts,wp_styles, and_wp_theme_featureshave been removed.data_wp_hoist_late_printed_styles():inline_size_limitandexpected_styles, and new test cases have been added to cover various scenarios (e.g., min/max inline styles, opting out of separate block styles, disabling block library).test_wp_hoist_late_printed_styles():switch_theme('default')is called earlier. Filters forstyles_inline_size_limitandwp_get_custom_cssare added.wp_load_classic_theme_block_styles_on_demand()andregister_core_block_style_handles()are explicitly called. A new helperensure_style_asset_file_created()is used to create necessary CSS files for testing.wp_enqueue_stylenow useshttps. Thewp_hoist_late_printed_styles()call is conditional.the_contentfilter is applied. Assertions are updated to use the new$expected_stylesarray and a new helperget_array_snapshot_export().ensure_style_asset_file_created()helper makes the tests more robust by not relying on a prior build step. The expanded assertions and theget_array_snapshot_export()helper significantly improve the maintainability and clarity of the test suite, especially for snapshot testing. The@ticketand@coverstags are correctly used.Conclusion:
The changes are well-implemented and significantly improve the handling of late-printed styles in classic themes, particularly for block styles. The accompanying test suite is comprehensive and robust. The temporary
phpcompat.xml.distexclusion should be addressed in the future.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.