<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ahmed</title>
    <description>The latest articles on DEV Community by Ahmed (@sm3rta).</description>
    <link>https://dev.to/sm3rta</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F882925%2F74c0ab11-279d-4c26-87fa-57760015ef0f.jpg</url>
      <title>DEV Community: Ahmed</title>
      <link>https://dev.to/sm3rta</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sm3rta"/>
    <language>en</language>
    <item>
      <title>Versioned web components and micro front-ends</title>
      <dc:creator>Ahmed</dc:creator>
      <pubDate>Mon, 09 Jun 2025 17:37:43 +0000</pubDate>
      <link>https://dev.to/sm3rta/versioned-web-components-and-micro-front-ends-1m40</link>
      <guid>https://dev.to/sm3rta/versioned-web-components-and-micro-front-ends-1m40</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Ever wondered if you can have two custom elements with the same name on one page? Would there even be a use case for something like this?&lt;/p&gt;

&lt;p&gt;Well, imagine the following scenario:&lt;/p&gt;

&lt;p&gt;You’re working with a micro-frontend (MFE) architecture where each MFE is an independent application relying on a shared UI library of web components. Sounds great, right? But here’s the catch:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The UI library is versioned.&lt;/li&gt;
&lt;li&gt;Different MFEs might depend on different versions of the library.&lt;/li&gt;
&lt;li&gt;Upgrading all MFEs to the latest version simultaneously is a logistical nightmare.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Why is this a problem? Well, web components use the global namespace for their custom elements. This means you can’t define two versions of the same element (e.g., &lt;code&gt;v1&lt;/code&gt; and &lt;code&gt;v2&lt;/code&gt; of the same component) with the same name in the same document.&lt;/p&gt;




&lt;h2&gt;
  
  
  Scoped Registries: A Glimmer of Hope
&lt;/h2&gt;

&lt;p&gt;Thankfully, some brilliant minds have already thought about this problem. Enter the concept of &lt;strong&gt;Scoped Custom Element Registries&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Back in &lt;strong&gt;&lt;em&gt;2020&lt;/em&gt;&lt;/strong&gt;, a proposal was introduced (&lt;a href="https://github.com/WICG/webcomponents/blob/gh-pages/proposals/Scoped-Custom-Element-Registries.md" rel="noopener noreferrer"&gt;Scoped Custom Element Registries&lt;/a&gt;) to solve this exact issue. The idea? Allow multiple versions of a custom element to coexist in the same document by assigning each MFE its own custom element registry. Each registry would contain the element definitions specific to the version of the library that the MFE depends on.&lt;/p&gt;

&lt;p&gt;This would allow multiple versions of a custom element to coexist in the same document, but the catch is that it hasn’t been implemented in browsers yet.&lt;/p&gt;




&lt;h2&gt;
  
  
  Polyfill
&lt;/h2&gt;

&lt;p&gt;Since the proposal hasn’t made it into the web spec, we have a polyfill: &lt;a href="https://github.com/webcomponents/polyfills/blob/master/packages/scoped-custom-element-registry/src/scoped-custom-element-registry.ts" rel="noopener noreferrer"&gt;@webcomponents/scoped-custom-element-registry&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But like any hero, this polyfill has its flaws. But to talk about limitations we need to understand first how it works under the hood&lt;/p&gt;

&lt;h3&gt;
  
  
  How the Polyfill Works
&lt;/h3&gt;

&lt;p&gt;The polyfill essentially hijacks the browser’s &lt;code&gt;window.customElements&lt;/code&gt; registry and replaces it with a shimmed version.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Save the native registry&lt;/strong&gt;: It stores the value of &lt;code&gt;window.customElements&lt;/code&gt; in a variable and sets it aside, since this is what the browser understands and uses to register and render custom elements.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nativeRegistry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;customElements&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Create a custom registry class&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ShimmedCustomElementsRegistry&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;CustomElementRegistry&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;elementClass&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CustomElementConstructor&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Introduce a "stand-in" class&lt;/strong&gt;: When a tag is defined for the first time, a stand-in class is created to act as a router. It looks up the correct registry and renders the appropriate version of the element.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;standInClass&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;nativeGet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nativeRegistry&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tagName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;standInClass&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;standInClass&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createStandInElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tagName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;nativeDefine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nativeRegistry&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tagName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;standInClass&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Registry lookup&lt;/strong&gt;: The lookup method in the stand-in element is to get the registry assigned to the nearest shadow root or the document (by calling &lt;code&gt;getRootNode().registry&lt;/code&gt; as an oversimplification)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;registryForNode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;ShimmedCustomElementsRegistry&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Patch the stand-in element&lt;/strong&gt;: After finding the correct registry, the stand-in element is patched to the appropriate definition.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;definition&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;customize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;definition&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Replace the global registry&lt;/strong&gt;: Change the class constructor with the customized class&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CustomElementRegistry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ShimmedCustomElementsRegistry&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;then change &lt;code&gt;window.customElements&lt;/code&gt; to an instance of the newly created class&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;defineProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;customElements&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CustomElementRegistry&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;configurable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;writable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Issues with the Polyfill
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. Idempotency
&lt;/h4&gt;

&lt;p&gt;Current latest version of the polyfill at the time of writing (&lt;code&gt;0.1.0&lt;/code&gt;) is not idempotent, meaning that if you load the polyfill multiple times which is kind of the expectation with MFEs, it will throw an error. There's &lt;a href="https://github.com/webcomponents/polyfills/issues/615" rel="noopener noreferrer"&gt;an open issue for this&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix&lt;/strong&gt;: Wrap the polyfill in a function that checks if it’s already loaded.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;scopedRegistryPolyfill&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Check if polyfill has already been applied&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;__SCOPED_CUSTOM_ELEMENTS_POLYFILL_APPLIED__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Mark as applied&lt;/span&gt;
  &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;__SCOPED_CUSTOM_ELEMENTS_POLYFILL_APPLIED__&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// ... rest of the polyfill code&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  2. React Support
&lt;/h4&gt;

&lt;p&gt;React’s virtual DOM lifecycle causes issues with the registry lookup. By the time the stand-in element constructs a node, it hasn’t connected to the DOM yet, so &lt;code&gt;getRootNode()&lt;/code&gt; fails to find the correct registry.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;instance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Reflect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;NativeHTMLElement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setPrototypeOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;HTMLElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;registry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;registryForNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="cm"&gt;/* this is always undefined */&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;customElements&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="cm"&gt;/* so it always falls back to global registry */&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;definition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;registry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_getDefinition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tagName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Fix&lt;/strong&gt;: Move the registry lookup to the &lt;code&gt;connectedCallback&lt;/code&gt; method.&lt;/p&gt;

&lt;h4&gt;
  
  
  3. Nested Web Components
&lt;/h4&gt;

&lt;p&gt;The polyfill doesn’t handle nested web components. For example, if a calendar component uses a button component internally, only the calendar component gets rendered.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix&lt;/strong&gt;: Recursively customize child components in the &lt;code&gt;connectedCallback&lt;/code&gt; method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;customizeChildren&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Element&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nf"&gt;requestAnimationFrame&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;shadowRoot&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;*&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;child&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;child&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tagName&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;-&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="cm"&gt;/* means it's a web component */&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;definition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;registry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_getDefinition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
     &lt;span class="nx"&gt;child&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;localName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;definition&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="nf"&gt;customize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;child&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;HTMLElement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;definition&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
     &lt;span class="c1"&gt;// Forward the registry to the shadowRoot so that lookup (registryForNode) works correctly&lt;/span&gt;
     &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;child&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;shadowRoot&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;registry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;registry&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
     &lt;span class="nf"&gt;customizeChildren&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;child&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
 &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nf"&gt;customizeChildren&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Forked Polyfill and Proof of Concept
&lt;/h2&gt;

&lt;p&gt;To address these issues, I’ve forked the polyfill and made some improvements. You can find the updated version and a working demo in &lt;a href="https://github.com/sm3rta/versioned-web-components-mfe" rel="noopener noreferrer"&gt;this repo&lt;/a&gt;. The demo showcases two versions of the same web component coexisting on a single page using React and Vite.&lt;/p&gt;

&lt;h3&gt;
  
  
  Project Setup Instructions
&lt;/h3&gt;

&lt;p&gt;For each MFE and the host you need to do the following&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Lazy load your apps&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;In the root file of each MFE:

&lt;ul&gt;
&lt;li&gt;Run the polyfill.&lt;/li&gt;
&lt;li&gt;Create a new registry.&lt;/li&gt;
&lt;li&gt;Wrap your app in a shadow DOM and pass the registry to it.&lt;/li&gt;
&lt;li&gt;Export the registry object and registry all custom elements using the locally scoped registry.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Footnote
&lt;/h2&gt;

&lt;p&gt;Even with the success of the proof of concept, as it stands, the current state of the proposal and the polyfill hints that it's not worth it to fix this problem head on and instead use a not-so-terrible workaround: &lt;em&gt;namespacing&lt;/em&gt;!&lt;/p&gt;

&lt;p&gt;In theory, if you can give your consumers the ability to prefix component names before defining them, they could choose different prefixes leading to different component names in each micro front end.&lt;/p&gt;

&lt;p&gt;For example, instead of v1 and v2 of &lt;code&gt;&amp;lt;my-button&amp;gt;&lt;/code&gt; share the same name, requiring a router stand-in component, we use&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;v1-my-button&amp;gt;&lt;/code&gt; in one app,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;v2-my-button&amp;gt;&lt;/code&gt; in another...&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Additional Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://micro-frontends.org/" rel="noopener noreferrer"&gt;Micro front-ends&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/Web_Components" rel="noopener noreferrer"&gt;Web Components Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://html.spec.whatwg.org/multipage/custom-elements.html" rel="noopener noreferrer"&gt;Custom Elements Specification&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dom.spec.whatwg.org/#shadow-trees" rel="noopener noreferrer"&gt;Shadow DOM Specification&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Happy coding! 🤖&lt;/p&gt;

</description>
      <category>microfrontend</category>
      <category>webcomponents</category>
      <category>semver</category>
      <category>mfe</category>
    </item>
  </channel>
</rss>
