When multiple web-component are used on the same site only one works
Vue version
3
Link to minimal reproduction
https://github.com/davidedisalvo/webComponent1
Steps to reproduce
- Clone both webComponent 1 and webComponent 2: https://github.com/davidedisalvo/webComponent1 https://github.com/davidedisalvo/webComponent2 (They have the same set up I just changed some name for demonstration purpose).
- Run
pnpm install
in both. - Run
pnpm build
in both. - Host the output. I have done this already: https://webcomponent1.netlify.app/index.js https://webcomponent2.netlify.app/index.js
- Use the 2 javascript output in a html page. I have done this here https://github.com/davidedisalvo/testSite and you will see just 1 web-component instead of 2. https://testsitewithwebcomponent.netlify.app/
What is expected?
Expect both web-components to load.
What is actually happening?
Our use case is to ship web-components to clients that has a site powered by headless CMS, hence the custom element and the javascript that powers it is loaded dynamically. Also our clients sites may not be using Vue. So we have to bundle the Vue runtime as part of the output javascript. We noticed that using our setup in vite config it will bundle the vue runtime and it will declare functions in the window object/global scope. In one instance we found out that it was overwriting window.addEventListener
and crashing client sites. We assumed it is due to a failed uglify output. Although we can't no longer reproduce this particular case we learnt that it is injecting things into the window object which may cause name conflicts when more than 1 web-component javascript is loaded on the same site.
You can see the console error here: https://testsitewithwebcomponent.netlify.app/
It says: Identifier 'gs' has already been declared (at index.js:1:1)
System Info
No response
Any additional comments?
No response
It seems you are using the esm build version of your libs and then include them as normal scripts. These files are meant to be used as models though (<script type="module">
). if you include them as a plains script, they will add all of their code to the global namespace, which is why you see all of these namespace clashes.
Solution: use the iife or umd version of your built files.
Not related to Vue or web components in any way.