We are using LitElement to build custom components (not public). Let's call it CompA and CompB. We are publishing the packages using CDN.
We use it in HTML via Script tag of type module. And each component works fine when it is the only component on the page. The moment we import CompA and CompB on the same page, we have a problem.
Uncaught DOMException: Failed to execute 'define' on 'CustomElementRegistry': the name "dom-module" has already been used with this registry
I know the problem is arising because of use of similar set of UI components across CompA and CompB. Probably paper-input, paper-button etc.
Is there a way to avoid this error by have better control over naming CustomElementRegistry and name other than "dom-module" when building your components using LitElement.
Update: I think I wasn't clear enough when asking so I have updated the question.
this problem is a really good reason for component libraries to leave component registration up to the consuming application
in my component libraries, i offer a simple function called registerComponents
function dashify(camel) {
return camel.replace(/([a-zA-Z])(?=[A-Z])/g, '$1-').toLowerCase()
}
export function registerComponents(components) {
for (const componentName of Object.keys(components))
customElements.define(dashify(componentName), components[componentName])
}
this makes it really easy for consumers to register components
the function simply converts the component names from camel case to dashed names (eg ShopperCart becomes shopper-cart)
my component libraries provide a convenience module called register-all.js, which performs all the registrations similarly to how a consumer might if they do this manually
import {ShopperCart} from "./components/shopper-cart.js"
import {ShopperButton} from "./components/shopper-button.js"
import {ShopperProduct} from "./components/shopper-product.js"
import {ShopperCollection} from "./components/shopper-collection.js"
import {registerComponents} from "./toolbox/register-components.js"
registerComponents({
ShopperCart,
ShopperCollection,
ShopperButton,
ShopperProduct
})
with this approach, it's really easy to rename components
registerComponents({
MyCart: ShopperCart
})
of course, in this case, a consumer can choose to simply import the convenient register-all.js to stick with the standard names
import "shopper/dist/register-all.js"
so to be clear, it's a bad pattern to use a customElements.define call within each component module, because we want to allow consumers some flexibility
you don't have to use or offer the handy registerComponents i suggest, but the important thing is that the consumer gets to choose how registration is handled
cheers, 👋 chase
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With