Open mtias opened 2 years ago
This is the same as #38911
Unfortunately, we don't have a good way yet to isolate resolvers or apiFetch requests or any sync behavior when loading patterns (in order to show the loaders properly).
Any ideas @tyxla @jsnajdr This could have a big impact on UX in a lot of places.
I haven't dug in-depth here just yet, but at first glance, this looks like a missed chance to preload some menus or pages' endpoint data. Or it's possible that the pre-existing navigation preloading doesn't work for some reason—IIRC, the endpoint parameters on the backend needed to match the ones on the front end perfectly for the preloading middleware to work. If that data is correctly preloaded, these blocks should load properly on the first render. @jsnajdr is this something you could investigate?
Alternatively, we could experiment with implementing a loading spinner for each pattern that needs more time to load, although ideally, they shouldn't take that long. That would capture any requests that blocks inside the pattern preview perform after the iframe loads, though. But it might require some additional tooling: as @youknowriad mentioned we currently don't have a good way to know which requests are blocking a particular pattern preview. This could be another area to experiment in.
Furthermore, there could be some little improvements we could do here. What if the pattern previews fade in with a small delay, concealing at least some of the initial rendering glitches or FOUC? Something like this:
https://github.com/user-attachments/assets/9499781f-304c-4075-8ce0-052f72b029a1
I haven't dug in-depth here just yet, but at first glance, this looks like a missed chance to preload some menus or pages' endpoint data.
I don't really think that's the main issue here, remember that the site editor is basically an SPA and that pages and templates can contain any random number of menus, template parts, reusable blocks... In other words, preloading means preloading the whole database is not the right solution for me.
Alternatively, we could experiment with implementing a loading spinner for each pattern that needs more time to load, although ideally, they shouldn't take that long. That would capture any requests that blocks inside the pattern preview perform after the iframe loads, though.
I think we keep avoiding this approach but I feel this is the right thing to do, it's not easy obviously but I wonder if we can find a creative way to do that.
I don't really think that's the main issue here, remember that the site editor is basically an SPA and that pages and templates can contain any random number of menus, template parts, reusable blocks... In other words, preloading means preloading the whole database is not the right solution for me.
I agree. There might be some low-hanging fruits there, though, since we're already preloading some navigation endpoints, and navigations still take a few requests to load.
I think we keep avoiding this approach but I feel this is the right thing to do, it's not easy obviously but I wonder if we can find a creative way to do that.
Indeed. I believe it's totally doable, and I'm confident we can give it a try.
To be fair, I was hoping we were able to pull static block preview rendering off, as that would solve most of the performance and user experience issues: https://github.com/WordPress/gutenberg/issues/54999
If we can achieve it, that remains the best alternative since we won't have to think about hacks and smart loading experiences that don't substantially improve the end-user experience.
Preloading can work, but it's a different kind of preloading than createPreloadingMiddleware
. It's the _embed
query param for REST API requests.
When loading /posts/123
the response has a numeric author
field that contains only the author ID. But with /posts/123?_embed=author
you'll get the full author object in _embedded.author
.
Similar kind of preloading could also work for entities referenced from the content. Patterns often link to other patterns (wp:pattern { slug="..." }
), the post-author-name
block uses the current user resource... The server could know these dependencies, by parsing the content, and from block.json
info, and when ?_embed=content:blocks
is requested, it could send it all along.
Makes sense @jsnajdr. Is this preloading something you wish to experiment with?
This could be interesting for multiple people:
canUser
selector, extracting separate info from the Allow
header. Now it would be generalized to extract everything possible from the _embedded
field.Thanks for the ping, @jsnajdr!
I like the idea of resolving embedded resources, though it might be difficult without tacking relations between entities/resources (I'm not sure if the query builder concept could be applied here).
parsing the content block markup on the server and doing something with the parsed blocks
I think @ellatrix implemented this for the patterns in the recent release - #60349.
This one also comes to mind: https://github.com/WordPress/gutenberg/issues/54999 cc @draganescu and @kevin940726
parsing the content block markup on the server and doing something with the parsed blocks -- did @ockham do this when implementing block hooks?
Thank you for the ping, @jsnajdr! Yeah, for Block Hooks, we are parsing, traversing, and re-serializing templates, template parts, patterns, and wp_navigation
objects on the server. This could possibly be extended to run some additional processing. You might want to have a look at traverse_and_serialize_block
plus some of the visitors (or rather, visitor factories) we're using.
Also, can @dmsnell's HTML API be useful here?
FWIW, for any operations that need to happen at block level (vs at HTML tag level), Dennis has advised against using the HTML API, and to use a block-level parser instead (as the rules that govern block syntax are much more rigid and thus easier to implement -- and more performantly so -- than is possible with the notoriously complex HTML spec). For Block Hooks, we started experimenting with a lazy parser a while ago, which should improve performance over the parse/traverse/serialize dance. The experiment has been stalled for a while, but I'm hoping to pick it up in the next couple of weeks.
I've been tinkering with a naive and presumptuous alternative, where we're loading the patterns behind the screen based on the presence of currently resolving requests:
Obviously, it needs lots of love, but I'm curious to hear early thoughts.
At the moment, patterns seem to go through a few rendering adjustments before settling into their final form. I'm spotting at least three but there could be more.
It'd be great to solve this as it makes the pattern inserter and the pattern experience feel more fragile.
cc @youknowriad @tyxla @jsnajdr as it also relates to https://github.com/WordPress/gutenberg/pull/42525