-
Notifications
You must be signed in to change notification settings - Fork 4.2k
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
Interactivity API: Delay block hydration to allow interactive block stores to initialize #66772
Conversation
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 If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.
To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
Thanks for investigating and creating the PR @westonruter ! 🙂 The current solution does fix the problem. However, even with the current workaround, the issue will persist if I remove or comment out the I'm currently trying to figure out a better way to handle this. |
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.
As @michalczaplinski commented, we can work in a follow-up PR to find a better solution. Meanwhile, I'll merge it and include it on today's Gutenberg release.
I just cherry-picked this PR to the release/19.6 branch to get it included in the next release: f4b013f |
Co-authored-by: westonruter <[email protected]> Co-authored-by: michalczaplinski <[email protected]> Co-authored-by: annezazu <[email protected]> Co-authored-by: artemiomorales <[email protected]> Co-authored-by: cbravobernal <[email protected]> Co-authored-by: t-hamano <[email protected]>
@michalczaplinski Really? I commented out the diff --git a/packages/interactivity/src/init.ts b/packages/interactivity/src/init.ts
index fa1eec51c3e..adc17a6458e 100644
--- a/packages/interactivity/src/init.ts
+++ b/packages/interactivity/src/init.ts
@@ -40,17 +40,17 @@ export const init = async () => {
* This occurs when splitTask() is implemented with scheduler.yield() as opposed to setTimeout(), as with the former
* split tasks are added to the front of the task queue whereas with the latter they are added to the end of the queue.
*/
- await new Promise( ( resolve ) => {
- setTimeout( resolve, 0 );
- } );
+ // await new Promise( ( resolve ) => {
+ // setTimeout( resolve, 0 );
+ // } );
for ( const node of nodes ) {
if ( ! hydratedIslands.has( node ) ) {
- await splitTask();
+ // await splitTask();
const fragment = getRegionRootFragment( node );
const vdom = toVdom( node );
initialVdom.set( node, vdom );
- await splitTask();
+ // await splitTask();
hydrate( vdom, fragment );
}
} And I get these errors: |
@westonruter, I'm unsure what you mean 🙂. I think that we're in agreement that the |
@michalczaplinski Oh, hah, sorry! I misunderstood. |
Sorry, I should have been more clear earlier too 🙂 . Here's my expanded explanation with additional details: Adding However, relying on I'm not sure if there's a better solution at this point than what was merged in the current PR. @DAreRodz and I have considered wrapping the |
AFAIK, the |
right, exactly 🙂 |
Co-authored-by: westonruter <[email protected]> Co-authored-by: michalczaplinski <[email protected]> Co-authored-by: annezazu <[email protected]> Co-authored-by: artemiomorales <[email protected]> Co-authored-by: cbravobernal <[email protected]> Co-authored-by: t-hamano <[email protected]>
@DAreRodz let's take a look at this for WordPress 6.8 to see if we can ensure there are no issues when stores initialize after the That being said, it's okay for the blocks that load initially to do so before the init function, as it is happening today (because we can optimize a few things in the init function itself). |
Fixes #66691.
When
scheduler.yield()
is available, thesplitTask()
function is implemented to use it. When a task is split withscheduler.yield()
it results in the tail being added to the front of the task queue. In contrast, whensplitTask()
is implemented withsetTimeout()
(whenscheduler.yield()
is not available), then the tail of the split task is added to the end of the task queue. It appears there is a race condition between the call toinit
.In particular, given this
init
function:gutenberg/packages/interactivity/src/init.ts
Lines 30 to 46 in 7f49b39
It is getting invoked before the code in a block's
view.js
is invoked, for example:gutenberg/packages/block-library/src/image/view.js
Line 22 in 7f49b39
When
splitTask()
is was usingsetTimeout()
then the calls toawait splitTask()
had the effect of delaying the hydration until after the blocks' view modules execute. But whensplitTask()
is implemented withscheduler.yield()
the hydration logic is executing before the interactive blocks' view module (i.e. the store initialization) executes.Of note, the error also occurs if
await splitTask()
is eliminated frominit
function as well, indicating that it was not correctly accounting for delaying the Interactivity API'sinit
until after the interactive blocks have all initialized. There seems to be a dependency problem here, where hydration of an interactive block should be blocked until its corresponding view script module has loaded. This seems to be related to:In the mean time, adding a
setTimeout()
to handle the delay seems to do the trick.Code execution with
splitTask
implemented withsetTimeout
gutenberg/packages/interactivity/src/init.ts
Lines 31 to 38 in 7f49b39
gutenberg/packages/block-library/src/image/view.js
Line 22 in 7f49b39
gutenberg/packages/interactivity/src/init.ts
Lines 39 to 46 in 7f49b39
Code execution with
splitTask
implemented withscheduler.yield
gutenberg/packages/interactivity/src/init.ts
Lines 30 to 46 in 7f49b39
gutenberg/packages/block-library/src/image/view.js
Line 22 in 7f49b39