Skip to content
This repository has been archived by the owner on Jul 28, 2023. It is now read-only.

Tracking issue: Custom Elements Hydration 🧩 #39

Closed
luisherranz opened this issue Jun 30, 2022 · 43 comments
Closed

Tracking issue: Custom Elements Hydration 🧩 #39

luisherranz opened this issue Jun 30, 2022 · 43 comments

Comments

@luisherranz
Copy link
Member

luisherranz commented Jun 30, 2022

This issue aims to list and keep track of the tasks related to the Custom Elements Hydration experiment.

For the Directives Hydration experiment, please check the Tracking Issue: Directives Hydration ⚛️.

The main branch of this experiment is main-custom-elements-hydration. Make sure you select it when opening a pull request if it is related to this experiment.

Please proactively comment on this issue whenever you start working on a new task, get blocked, or finish a task, sharing as much detail and information as possible. Thanks!!

Done

Required to expose as experimental API in Gutenberg

Future improvements

@luisherranz
Copy link
Member Author

Previous video summaries

Originally posted in #6

Update 1

https://www.loom.com/share/549258dfe6844fe0b3fdc8c3fc856b13

For context, when I mention Turbolinks in the video, I'm referring to this type of client-side navigation: WordPress/gutenberg#38713

Update 2

https://www.loom.com/share/e5a5541d027d4149a91a70f30b0913be

Resources mentioned:

@luisherranz luisherranz pinned this issue Jun 30, 2022
@cbravobernal
Copy link
Collaborator

I'm currently working on #38. Still digging and trying to discover the best way to duplicate the Context Provider and sync the value of that context.

@michalczaplinski
Copy link
Collaborator

I have started working on adding support for providing context from non-interactive blocks.

@cbravobernal
Copy link
Collaborator

Added a WIP draft PR for #38 -> #40

@michalczaplinski
Copy link
Collaborator

Resharing this brief status update on my work on #28:

I was able to make it work so far in the simplest case: one static (non-interactive) parent and one child interactive block 👍 .

Most immediate next steps would be:

  • Making it work with multiple parents. An interactive block can inherit context from multiple parent blocks.
  • Making it work with initially hidden blocks. Adding a global event listener on load does not work because if a new interactive block is dynamically added to the DOM, it will not be subscribed to the events! I guess we have to encapsulate this code in the connectedCallback() of our <gutenberg-interactive-block> custom component.

@michalczaplinski
Copy link
Collaborator

I've finished the work on Support providing context from non-interactive blocks #28. It's gonna go through some review now but should be close to what we want to merge 🙂 .

@cbravobernal
Copy link
Collaborator

The React Context API subtasks are 90% complete! We still need to check how it works on the editor, where it should be easy.

I will update the tracking issue again as soon as we unsubscribe the contexts after using them.

@luisherranz
Copy link
Member Author

I've opened an issue to see how we could unmount the interactive-block components before they are removed from the DOM:

@luisherranz
Copy link
Member Author

luisherranz commented Jul 14, 2022

I've also added Matías' nomenclature suggestions to the list, although I'd wait until the rest of the PRs are merged to avoid merge conflicts.

@cbravobernal
Copy link
Collaborator

cbravobernal commented Jul 14, 2022

The last commits are adding a double Map to link blocks to context, and then the values and update values functions to those block->Context-> Value

On the other hand, I will next take a look if we can suppress custom warnings for the useEffect, or either way, look for an alternative to run the code once without it.

Weakmap seems to be valid in most edge cases, but @luisherranz offered to take a deeper view to see if it fits our requirements.

I will then wait for #28 to be merged, so we can check later if there are any conflicts and we can start testing altogether.

@michalczaplinski
Copy link
Collaborator

Luis has suggested that we try a slightly different approach in that PR in order to avoid using a custom element to wrap all blocks that pass context.

The idea is to serialize the context and pass it as an HTML attribute of the top-level HTML element of the block itself (as opposed to setting it on the custom element). Then, we can use a MutationObserver on the document to detect changes to the DOM and pass the context whenever that happens. This is necessary because the "new", updated DOM might contain new interactive blocks that are subscribed to some piece of context.

My worry is that this can have poor performance because we'll have to fire the MutationObserver callback on every DOM change and the DOM changes can come from unexpected sources (browser extensions, ads, third party scripts, etc.)

Next step: I will make a quick test to try to see how bad the new implementation would perform if there are very frequent DOM updates.

@cbravobernal
Copy link
Collaborator

-#40 status update:

I added another Context to see if it works and seems to be failing. Feel free to keep working on that, as I will be 2 weeks AFK!

@luisherranz
Copy link
Member Author

Before we start adding code to the WooCommerce Block Hydration Experiments repo, I'd like to finish the three PRs we have open right now:

And once those are merged, I'd like to do the nomenclature refactor:

Not important for Woo, but at that point, I'd also like to remove dprint, and test prettier with the prettier-php plugin.

@luisherranz
Copy link
Member Author

I've finished the support for the React Context API (#40), including a code refactoring of frontend.js, which was getting a bit out of hand (d61391c). I've also resolved the conflicts on #28 and I'm working to resolve them in #41.

@luisherranz
Copy link
Member Author

luisherranz commented Jul 22, 2022

I've switched to prettier in #43 and resolved conflicts on #28 and #41.

@michalczaplinski, @ockham everything should be fine now.

Once you finish, I'll do the nomenclature changes.

@luisherranz
Copy link
Member Author

luisherranz commented Jul 25, 2022

#28 should be ready now. I've made a video to explain the changes because I unified everything in gutenberg-block.

I want to take a fresh look at the inner blocks template to see if we can avoid this problem now (and don't wait if/until we do this in Gutenberg):

EDIT: BTW, I also added prettier-php in #28 to test it out.

@luisherranz
Copy link
Member Author

@ockham finished #41 🎉🎉

I'm going to resolve the conflicts with #28.

@luisherranz
Copy link
Member Author

I'm going to resolve the conflicts with #28.

Done. I think everything should be ready now.

@michalczaplinski
Copy link
Collaborator

As Luis mentioned in this comment already, the approach of using the MutationObserver did not work so we're still going to wrap the non-interactive blocks with a custom element. However, Luis has moved the serialization to PHP so we're not saving the context in the content in save() anymore.

@luisherranz
Copy link
Member Author

Thanks, Michal 🙂

I'll work on #37 today, and if I can, I'll check if #29 can be solved during render_block.

@luisherranz
Copy link
Member Author

I've opened an issue to talk about prettier-php. If you're playing with this repository, please help us test it and if you have any problem, please report it here:

@luisherranz
Copy link
Member Author

The PR for the nomenclature changes is ready for review:

@luisherranz
Copy link
Member Author

Update 3

Ok, now that we've kind of reached another milestone, I did another video summary to explain the latest changes.

https://www.loom.com/share/3b68a95ac80f43ecbe86ca8225cb35a0

@luisherranz
Copy link
Member Author

I've opened a new issue for the bug I discovered during the video:

@michalczaplinski
Copy link
Collaborator

The PR for the nomenclature changes is ready for review:

I've merged this PR as well! 🙂

@SantosGuillamot
Copy link
Contributor

I've created this repo to replicate the experiments done here but using Alpinejs. The main idea is to be able to compare the developer experience and limitations of both approaches. Right now, I just recreated the current blocks, but we will probably run a few more tests there.

@DAreRodz
Copy link
Collaborator

DAreRodz commented Aug 5, 2022

I took the liberty of merging the fix for the WpBlock unmounting issue (#42) as it was a simple PR and was tested already. 😄

I also updated the tracking issue description with the latest changes.

@luisherranz
Copy link
Member Author

I've updated the Up Next list with two new items:

  • Add support for frontend-side i18n
  • Research how to hydrate different block variations

@ockham
Copy link
Collaborator

ockham commented Aug 9, 2022

I've filed #51 (which Carlos approved and merged -- thanks!) to fix

@luisherranz
Copy link
Member Author

I've opened the issue to make sure the order of execution of the registerBlockType() and connectedCallback is not important:

@luisherranz
Copy link
Member Author

luisherranz commented Aug 24, 2022

@DAreRodz and I have explored a fix for the race condition problem (#52):

Reviews are welcomed!

@DAreRodz
Copy link
Collaborator

I've discussed with @luisherranz what things we need to solve before exposing these APIs as experimental from Gutenberg.

It ended in a to-do list, included in the issue description. ☝️

@luisherranz
Copy link
Member Author

I've added a bit more context to the Export different code depending on the context issue.

@DAreRodz
Copy link
Collaborator

I created a new issue for the remaining item in the "Required for experimental API" list.

@luisherranz
Copy link
Member Author

I've added a proposal for an alternative wrapperless hydration method based on a static virtual DOM of the full page:

@luisherranz
Copy link
Member Author

luisherranz commented Aug 31, 2022

We opened a new issue to discuss possible solutions to locate the children of the islands/client-components (moved from #60):

@luisherranz luisherranz changed the title Tracking issue Tracking issue: Island Hydration Sep 6, 2022
@luisherranz luisherranz changed the title Tracking issue: Island Hydration Tracking issue: Island Hydration 🏝 Sep 6, 2022
@luisherranz
Copy link
Member Author

luisherranz commented Sep 6, 2022

@DAreRodz and I have created a new Tracking Issue to track the work related to the Directives Hydration:

From now on, please use this Tracking Issue for the Custom Elements Hydration experiment and the other one for the Directives Hydration experiment.

We've also renamed the main branch to main-custom-elements-hydration for this experiment and created a new one called main-directives-hydration for the other one. Please, select the correct branch when opening pull requests.

@SantosGuillamot
Copy link
Contributor

As explained in this issue, it looks like the setTimeout callback we are using inside connectedCallback is not 100% reliable. So we may need to look for an alternative.

@luisherranz luisherranz changed the title Tracking issue: Island Hydration 🏝 Tracking issue: Custom Elements Hydration 🧩 Oct 14, 2022
@luisherranz
Copy link
Member Author

luisherranz commented Oct 14, 2022

To avoid confusion, I've renamed "Island Hydration" to "Custom Elements Hydration" because both this and Directives are just ways of doing island hydration.

@luisherranz
Copy link
Member Author

Closed as we're not actively working on this experiment anymore. Our work continues in:

@fabiankaegy
Copy link
Member

Closed as we're not actively working on this experiment anymore. Our work continues in:

@luisherranz I've been trying to track down the reasons why this approach was abandoned :) Would you be able to shed some light on that? :) Thanks in advance!

@luisherranz
Copy link
Member Author

It had a few issues:

  • There's no easy way to use this approach with dynamic blocks.
  • Any dynamic markup modifications (done with PHP hooks) are not reflected on the JSX template and are reverted after hydration.
  • It also makes some things like internationalization much more complex than needed.

@fabiankaegy
Copy link
Member

Thanks for sharing that insight :)

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

7 participants