Skip to content

Enhanced Runtime Shadow DOM Support #3746

Open
@iammerrick

Description

@iammerrick

Clear and concise description of the problem

As a developer using Module federation enhanced runtime I want to use module federations that render into Shadom DOM instances from web components so that CSS can be isolated.

Suggested solution

In the loadRemote function we could provide a separate root, loadRemote(moduleId, shadowRoot). This would allow the user to declare where the CSS should be linked.

This would allow using federated modules inside of web components using shadow roots:

class CustomElement extends HTMLElement {
  constructor() {
    super();
    this.attachShadow({ mode: 'open' });
  }
  async connectedCallback() {
    if (!this.shadowRoot) return;

    const module = await loadRemote('dynamic-remote/button', {
      root: this.shadowRoot,
    });
    createRoot(this.shadowRoot).render(React.createElement(module.default));
  }
}

customElements.define('custom-element', CustomElement);

Since this element can be rendered multiple times, the CSS would need to be linked for each different root:

<custom-element /> // Link it in here
<custom-element /> // And in here

And if the the user doesn't provide a root, it should load it in the document.head using the behavior we have today:

const module = await loadRemote('dynamic-remote/button'); // Uses document.head!

In order for this to work, module federation can no longer assume "if it was loaded once, we're loaded and done!" it has to treat attachment as something that happens per root, which is not just about loading but how the browser indicates scoping for styles made available to shadow dom.

I've provided a PR here #3740 but it isn't complete because the preload cache assumes a single CSS attachment phase due to a global cache. I'm not sure the best path forward from here.

Alternative

I considered the idea of returning a different root via a runtime plugin, however, this suffers the same "it isn't a single attach phase anymore" problem and it doesn't naturally support the reality of multiple instances of a web component on a page, each component needed it's css attached.

Additional context

Encapsulation from CSS Shadow DOM

Validations

  • Read the Contributing Guidelines.
  • Check that there isn't already an issue that request the same feature to avoid creating a duplicate.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions