Our platform is built on a micro-frontend architecture with web components. We are using Stencil for some of them, this means we have multiple Stencil apps within one web page. Additionally, we have a UI library, also built with Stencil, which we want to use in these microfrontend components.
We would like to use the Stencil UI library as build-time dependency to the Stencil micro-frontend components. But this currently not possible due to tag name collisions:
Theoretically, two micro-frontends could ship two different versions of the UI library. However, at runtime, they would collide, as they’re both trying to register their UI elements with customElements.define. Of course, this doesn’t happen as Stencil checks for existing names before registering a new one – but the result is just as bad: The first loaded component always wins, and if it is an older version or has a different API, other components will break.
A solution would be namespacing/prefixing tag names at build or run time, but there is nothing in the web standards for this (yet). And while there is a namespace config option in Stencil, that doesn’t seem to solve this kind of problem.
With pure ES6, we could at least do the following (i.e. register a custom element with a dynamic tag name):
export class InnerComponent extends HTMLElement
{
static register(prefix) {
customElements.define(`my-${prefix}-inner-component`, InnerComponent)
}
constructor() {
super()
this.shadow = this.attachShadow({ mode: "open" })
}
connectedCallback() {
this.shadow.innerHTML = `<span>this is some UI component</span>`
}
}
And I’m sure we could employ some sort of build-time solution with Webpack etc. to achieve the same.
But is something similar possible with Stencil? Or how else can this be solved?