Closed RahiDroid closed 2 years ago
I can confirm this issue. It's a pretty major one 😬
Looks like the values are being saved to the styles custom post type, but are not being retrieved for some reason, will see if I can work out why that is.
It looks like in wordpress-develop this call is not returning the custom global styles data. The correct data is there in the preceding config var, ran out of time to try and work out why it is working in GB trunk and not 6.1 beta.
@oandregal may have some thoughts - this PR touched on some of these areas, but it all seems to have been ported to 6.1
Interestingly, in wordpress-develop I can save styles for server rendered blocks in global styles (e.g. site title), but not static blocks (like Group). Just in case that points in any particular direction for this one or the linked trac issue.
I think this one will likely need to be fixed from the core side, but I noticed (and commented here on the trac issue) that if we update the priority of the register_core_block_types_from_metadata
callback on the init
action to have a priority of 1
, that appears to resolve the issue (this line). So it sounds like it's likely related to a caching issue / order of calls with get_blocks_metadata
being called too early, like @jorgefilipecosta described? (While updating the priority worked in my local environment, I imagine that won't work as a proper fix, as it possibly obfuscates the real bug 🤔)
I can confirm that this issue does not occur with Gutenberg active. Only in 6.1 Beta. So it seemly like something might not have been ported over properly? 🤔
I've done some testing: go to the global styles sidebar and set the global background color and the background color of the heading block. This is how I'm tracing this data usage:
{
"styles": {
"color": { "background": "var:preset|color|vivid-red" },
"blocks": {
"core/heading": {
"color": { "background": "var:preset|color|luminous-vivid-amber" }
}
}
},
"isGlobalStylesUserThemeJSON": true,
"version": 2
}
WP_Theme_JSON_Resolver::get_user_data()
is this (notice how the block data is missing):(
[theme_json:protected] => Array
(
[styles] => Array
(
[color] => Array
(
[background] => var:preset|color|vivid-red
)
)
[version] => 2
)
)
So the data is properly saved but is discarded when rendering.
What happens is that, at some point, the theme.json class receives the data saved in the database. It wants to sanitize it. One of the things it does is removing data for blocks that are not registered. And, apparently, the core/heading
is not, hence its data is removed and the styles are generated without it. These are the "valid blocks" at the point the user data is first calculated:
(
[0] => core/legacy-widget
[1] => core/widget-group
[2] => core/archives
[3] => core/avatar
[4] => core/block
[5] => core/calendar
[6] => core/categories
[7] => core/comment-author-name
[8] => core/comment-content
[9] => core/comment-date
[10] => core/comment-edit-link
[11] => core/comment-reply-link
[12] => core/comment-template
[13] => core/comments
[14] => core/comments-pagination
[15] => core/comments-pagination-next
[16] => core/comments-pagination-numbers
[17] => core/comments-pagination-previous
[18] => core/comments-title
[19] => core/cover
[20] => core/file
[21] => core/gallery
[22] => core/home-link
[23] => core/image
[24] => core/latest-comments
[25] => core/latest-posts
[26] => core/loginout
[27] => core/navigation
[28] => core/navigation-link
[29] => core/navigation-submenu
[30] => core/page-list
[31] => core/pattern
[32] => core/post-author
[33] => core/post-author-biography
[34] => core/post-comments-form
[35] => core/post-content
[36] => core/post-date
[37] => core/post-excerpt
[38] => core/post-featured-image
[39] => core/post-navigation-link
[40] => core/post-template
[41] => core/post-terms
[42] => core/post-title
[43] => core/query
[44] => core/query-no-results
[45] => core/query-pagination
[46] => core/query-pagination-next
[47] => core/query-pagination-numbers
[48] => core/query-pagination-previous
[49] => core/query-title
[50] => core/read-more
[51] => core/rss
[52] => core/search
[53] => core/shortcode
[54] => core/site-logo
[55] => core/site-tagline
[56] => core/site-title
[57] => core/social-link
[58] => core/tag-cloud
)
I've quickly looked at the places where we require global styles data. Inspected the usage of the wp_get_global_stylesheet
(and similar functions) as well as the classes (WP_Theme_JSON
and WP_Theme_JSON_Resolver
). I wanted to learn if we had changed the places where we use this code (script-loader.php
, etc.) and made it so it runs earlier than block registration. I haven't found anything meaningful.
The other reason some blocks may not be registered at that point is that block registration had changed, as Jorge suggested in the trac ticket. A bit out of my expertise at the moment, and given some time-constraints I have this week I'm not sure if I'm going to be able to help investigate much further this path.
Thanks for writing all that up @oandregal — I think I've found where the caching issue is occuring:
After a git-bisect on wordpress-develop that pointed to this backport commit, I tried looking through the backported server-rendered blocks, and I think I've found the area that's causing the issue in the Template Part block's build_template_part_block_instance_variations
function. This function is called when the block is registered, rather than when it's rendered, and uses the get_block_templates function on this line, which appears to eventually further down the line call get_theme_data
here, causing the list of registered blocks to be cached.
If I update the following line in register_block_core_template_part
to set variations to null
, then global styles appears to be working correctly again: https://github.com/WordPress/wordpress-develop/blob/3b63a75108b7f6d5e9112c556285ab1bc80ddbcf/src/wp-includes/blocks/template-part.php#L248
So, the problem appears to be calling a getter function like this at registration time prior to all blocks being registered.
For a bit more background, this caused a few issues in the Gutenberg plugin earlier on. The solution at the time was to adjust the caching in Gutenberg, but it looks like this didn't get to the root of the problem for when the block was backported. Here are some earlier links:
The question now, then, is what's the right fix for this problem? @ramonjd mentioned the idea of potentially calling or adding an action to call clean_cached_data
again, similar to the switch theme action: add_action( 'switch_theme', array( 'WP_Theme_JSON_Resolver', 'clean_cached_data' ) );
.
I'm wondering if we should either a) avoid calling a getter function for theme data at registration time in the Template Part block, or b) work out a way to reliably clean the cached data at the right time once all blocks are registered. CC: @talldan in case this sparks any ideas, too.
Does anyone have any strong opinions on what the correct caching behaviour should be here?
I'm wondering if we should either a) avoid calling a getter function for theme data at registration time in the Template Part block, or b) work out a way to reliably clean the cached data at the right time once all blocks are registered. CC: @talldan in case this sparks any ideas, too.
A short term fix isn't a bad idea for 6.1. A longer term fix should also be investigated as this code is too fragile. get_block_templates
is a public function, and it's one that plugins could very well be interested in calling, so while there's some ability to fix this internally, the deeper problem is exposing brittle APIs for public consumption.
Possibly a quick fix would be to add a way to get templates without filling the theme json cache.
Looking at the deeper problem, to me it seems like there should be some cache invalidation at certain points.
There are also dependency issues. Getting template parts shouldn't require compiling and caching the entire theme json. A lot of the settings in theme json are completely unrelated, so it might be worth breaking the cache into smaller sub-caches. The filling and invalidation of those caches can then be optimized in a way that wouldn't have been possible before.
Thanks @talldan, you raise some great points! Ideally get_block_templates
wouldn't have such potentially risky side-effects 👍
In order to try to find a pragmatic short-term fix, I've opened up a core PR in https://github.com/WordPress/wordpress-develop/pull/3352 to try adding a comparable clean_cached_data
static method to the WP_Theme_JSON
class and call both it and WP_Theme_JSON_Resolver::clean_cached_data()
when the Template Part block has finished gathering its variations. I'm wrapping up for the day now, but happy to try to look into adding tests for it tomorrow if it looks viable (I'm not 100% sure how to reliably test for it, so also very happy for any ideas on that PR if anyone gets the chance 🙂)
I figure a core PR is a better way to test for a fix than doing it in the GB repo. Whichever fix we come up with, we can then port it back over to GB once it's landed.
Thanks @oandregal @andrewserong @talldan for helping track this down!
Upon reading @andrewserong's comment, especially this part:
[...] I think I've found the area that's causing the issue in the Template Part block's
build_template_part_block_instance_variations
function. This function is called when the block is registered, rather than when it's rendered, and uses the get_block_templates function on this line, which appears to eventually further down the line callget_theme_data
here, causing the list of registered blocks to be cached.
...I had one idea off the top of my head: It seems like there's actually a few unneeded function calls, mostly due to the fact that templates and template parts share a lot of logic. Specifically, we're obviously only interested in template parts here; still we end up calling WP_Theme_JSON_Resolver::get_theme_data()->get_custom_templates()
. But that's the list of custom page templates that are included in the theme -- which shouldn't have any bearing on template parts.
So maybe we can leverage the fact that we already know (and specify) that we're only interested in template parts upon invoking get_block_templates
in order to avoid calling functions that are only relevant to templates (but not parts) 🤔
Uh, nevermind. I think the line we're calling is this (rather than this), so it goes through _add_block_template_part_area_info
rather than _add_block_template_info
. That's the correct behavior; _add_block_template_part_area_info
just also happens to call WP_Theme_JSON_Resolver::get_theme_data()
-- albeit to chain it to ->get_template_parts()
rather than templates.
So no potential to fix this here 😬
I've filed an alternative fix here, based on y'all's findings: https://github.com/WordPress/wordpress-develop/pull/3359 😊
Great work @ockham, that feels much closer to an ideal fix. Just left a comment over on that PR — I think there's still a bit more fussing we need to do with the clearing the resolver cache to get the Button styling in TwentyTwentyTwo working again, but I think we're heading in the right direction!
Building on the idea @ockham is exploring, I've opened up another alternative PR in https://github.com/WordPress/wordpress-develop/pull/3373 which tries to be a bit more explicit about when we cache bust in the Theme JSON and Resolver classes — basically, trying to make sure that a change in the number of registered blocks results in the cache being regenerated for just what we need. I think this should fix the issue while still preserving the performance benefits of the current caching.
If anyone gets a chance to take a look, I can work through any feedback on Monday. CC: @talldan @jorgefilipecosta @oandregal
I've opened (yet another) PR in https://github.com/WordPress/wordpress-develop/pull/3392 to explore a potential solution. @ramonjd and @ajlende rightly pointed out that checking for the number of registered blocks can result in edge cases where the caching isn't busted when we expect it to be. In this alternative PR, I'm proposing adding a registered_block_type
action, and to use this to flush the Theme JSON and Resolver caches — that way it's ensured the caches are cleared whenever a block is registered, rather than attempting to infer the current state within the Theme JSON/Resolver classes.
Happy for any feedback / ideas if folks think a different approach would be better!
I've looked at alternatives and https://github.com/WordPress/wordpress-develop/pull/3392 (cleaning data when a new block is registered) sounds theoretically the best approach, though 1) we also need to consider that blocks can be unregistered as well, and 2) there are a few paths 3rd parties can use to register a block AFAIK.
It sounds like https://github.com/WordPress/wordpress-develop/pull/3359 may be a more robust fix for 6.1. We can look at this more holistically after 6.1.
Thanks for taking a look @oandregal! I think @ajlende's feedback about moving the "registered" hook to the WP_Block_Type_Registry
class would ensure we catch all block registrations (including 3rd party ones), and remove a little duplication. I'll have a play at updating https://github.com/WordPress/wordpress-develop/pull/3392 today.
I've updated https://github.com/WordPress/wordpress-develop/pull/3392 to move the hook to the registry class, which now seems to capture all cases where a block might be registered.
Update: We now have a few candidates to fix this issue:
clean_cached_data
method to WP_Theme_JSON
and uses that plus the existing WP_Theme_JSON_Resolver::clean_cached_data
method after registration of the Template Part block.WP_Theme_JSON::get_blocks_metadata
to add blocks metadata for any blocks that aren't cached yet.WP_Theme_JSON_Resolver::get_theme_data
.WP_Theme_JSON
and WP_Theme_JSON_Resolver
based on number of blocks.Finally, while not a fix to this issue, there's https://github.com/WordPress/gutenberg/pull/44658, which is a related minor performance and code quality improvement.
I'll review these alternatives in a follow-up comment and will try to draw up a strategy that we can take from here.
We have two partial fixes/improvements that I consider very low-risk:
WP_Theme_JSON::get_blocks_metadata
part only)
WP_Theme_JSON_Resolver::get_theme_data
). While that would fix the other part of the issue (theme.json
per-block Global Styles settings aren't applied; edit: I just learned that we have a separate issue for this: https://github.com/WordPress/gutenberg/issues/44619), the performance impact might be too big.I would then like to land those two.
This leaves us with the caching issue in WP_Theme_JSON_Resolver
. I would like to explore this suggestion by @oandregal for a bit, since it seems like it would tackle the caching issue at its core.
If we cannot get that ready in time, we might instead merge a fallback. I'm currently leaning towards https://github.com/WordPress/wordpress-develop/pull/3384, since it doesn't introduce any new APIs.
I think one important thing is to treat the issues separately:
WP_Theme_JSON
PR fixes the manual Global Styles-styling of buttons by the user (this issue).theme.json
stuff is broken because of WP_Theme_JSON_Resolver caching (#44619).@c4rl0sbr4v0 is currently looking into @oandregal's suggestion.
Update:
WP_Theme_JSON
caching fix; it's part of WP 6.1 Beta 3.I'm considering closing this issue (since it's arguably fixed), and moving discussion over to https://github.com/WordPress/gutenberg/issues/44619 (which AFAICS covers the remaining issue with the theme resolver). Thoughts? 👍 / 👎
I'm considering closing this issue (since it's arguably fixed), and moving discussion over to https://github.com/WordPress/gutenberg/issues/44619 (which AFAICS covers the remaining issue with the theme resolver). Thoughts?
Yeah, in my testing, this issue appears to be fixed in Beta 3
Thanks for weighing up all the options @ockham, and landing the incremental fixes! 🙇
I'm considering closing this issue (since it's arguably fixed), and moving discussion over to https://github.com/WordPress/gutenberg/issues/44619 (which AFAICS covers the remaining issue with the theme resolver). Thoughts? 👍 / 👎
That sounds good to me. Should we keep a trac issue open for #44619, though, as it's still a blocker for 6.1?
@c4rl0sbr4v0 is currently looking into @oandregal's https://github.com/WordPress/wordpress-develop/pull/3359#discussion_r985689298.
To keep efforts streamlined, I've closed out my alternate PRs now, but do ping me if you need a review on anything. Thanks for digging in to find the right solution!
That sounds good to me. Should we keep a trac issue open for https://github.com/WordPress/gutenberg/issues/44619, though, as it's still a blocker for 6.1?
Yeah, good point. I'll file one 👍
To keep efforts streamlined, I've closed out my alternate PRs now, but do ping me if you need a review on anything. Thanks for digging in to find the right solution!
Thank you for all your work and research! ❤️
That sounds good to me. Should we keep a trac issue open for #44619, though, as it's still a blocker for 6.1?
Yeah, good point. I'll file one 👍
Description
paragraph
,heading
,button
,site title
, etc. It doesn't seem to be happening with all of the blocks, though.Blocks
section still works.Step-by-step reproduction instructions
Copy pasting from the trac ticket,
Screenshots, screen recording, code snippet
https://user-images.githubusercontent.com/59014930/192104832-a8b0f526-0baf-41b9-8c7a-f1e57099fa58.mov
Environment info
Please confirm that you have searched existing issues in the repo.
Yes
Please confirm that you have tested with all plugins deactivated except Gutenberg.
Yes