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

Hydrate islands inside templates #172

Closed
luisherranz opened this issue Mar 8, 2023 · 1 comment
Closed

Hydrate islands inside templates #172

luisherranz opened this issue Mar 8, 2023 · 1 comment

Comments

@luisherranz
Copy link
Member

luisherranz commented Mar 8, 2023

With the current island hydration algorithm, islands inside a <template> tag will not work once the template tag is deleted.

For example, this wp-text will not work.

<div data-wp-interactive data-wp-context='{ "show": false }'>
  <template data-wp-show="context.show">
    <div data-wp-ignore>
      <div data-wp-interactive data-wp-context='{ "text" : "world" }'>
        Hello <span data-wp-text="context.text"></span>
      </div>
    </div>
  </template>
</div>

This is because the HTML that exists inside the template tags does not belong to the DOM, and document.querySelectorAll('[data-wp-interactive]') (code) will not return those elements.

There are several solutions:

  • Never use <template>.

    I don't like it, since using template tags has benefits.

  • Search data-wp-interactive in the content of each template tag

    Using something like this (needs to be recursive):

    document.querySelectorAll("template").forEach((template) => {
      template.content.querySelectorAll("[data-wp-interactive]");
      // ...
    });

    I don't like it either because hydrating content that is inside a template tag is doing extra work on page load. Ideally, hydration should happen when those elements appear in the DOM.

  • Finding a way to auto-hydrate islands when they appear in the DOM

    We would have to find a way similar to the one we used with the custom elements hydration where we used the connectedCallback to initiate the hydration once those elements appear in the DOM.

    Since we cannot use custom-elements (see this), I think the only way to do this would be to use MutationObserver.

    You could use customized built-in elements and use is="wp-interactive", but Safari will never support them. So instead of using a polyfill, we better use MutationObserver directly.

  • Manually execute the hydration in directives that use template tags, such as wp-show.

    Every time a directive pulls HTML content from a template, it would have to run a "rehydration" of that content, in case there were any new islands inside. Something along the lines of:

    if (!evaluate(show, { context })) {
      element.props.children = <template>{children}</template>;
    } else {
      element.props.children = children;
      reHydrate();
    }

    I don't like the idea of delegating that responsibility to developers. The framework should be self-sufficient to avoid bugs.

Any other ideas?

@michalczaplinski
Copy link
Collaborator

I think that by far the best solution out of the above is:

Finding a way to auto-hydrate islands when they appear in the DOM

We can make it work via a MutationObserver but we should consider whether using the customized built-in elements and is="wp-island" is a viable alternative. The polyfill itself is based on MutationObserver. So, in the end, I don't see a meaningful semantic difference between using a polyfill that uses MutationObserver and creating our own solution based on MutationObserver 🙂. Of course, it's very possible that rolling our own is more performant and smaller because we only need it for one narrow use case.

@WordPress WordPress locked and limited conversation to collaborators Jul 27, 2023
@luisherranz luisherranz converted this issue into a discussion Jul 27, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants