-
Notifications
You must be signed in to change notification settings - Fork 205
This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Importing components forces registration without check #1024
Comments
@Westbrook I am looking at the spec for the custom registry and I don't think that would fix this problem with SWC imports. In my example, I imported So, I could not import |
In the nearest term, I'm unsure whether there's a more realistic answer to this situation than; don't attempt to ship two individually bundled applications on the same page. The most zen/happy place for web components delivery at large is in a completely unbundled context where the module graph is being managed and deduplicated by the browser and no matter how many "applications" are on the same page their dependencies are resolved and shared without stepping on each other. This, I understand, is not always possible, and even with technologies like HTTP2+ and CDN and smart edge delivery it is not always going to support the highest quality delivery of an application to an end-user, though it's getting closer and closer. (I'll leave the benefits of unbundled delivery of applications in conjunction with Managing this context, as is... Why not It could be said that instead, we could rely on a warning gate instead of an error gate, which will certainly prevent deploy time failures, but it won't bring the situation of silent failures to light any earlier as a warning can be easily missed by even the most cautious of eyes or worse ignored as not actually being an error by tired/late/distracted eyes. What else could we do now? What if we are not in a hurry? What if we went big? How do we find the right path forward? Please chime in below so we can find a path forward to this situation that is productive for everyone... |
A simple path that occurs to me is to bake the version of a component into itself. Then, instead of just trying to register a component blindly. Check to see if the component is already registered and if the version of the registered version matches the version that wishes to now register. |
Note that I did find the Scoped Elements tool in my research. I thought of using that in one of the two apps. However, as noted, I cannot import the raw components (e.g. Dropdown) without registering other components as a side effect. |
To clarify my suggestions above, only the "Managing this context, as is..." section really speaks to options that would solve this from the outside. Scoped Elements would indeed not be something you could do at the app level today to avoid this situation. We could, today, prioritize a refactor in this way, if we needed to make immediate changes to support consumers. I outline my understanding of that decision in the space not specifically to dissuade that course of action but to clarify the costs of such a decision. Another option from the outside, a consuming app could leverage all dynamic imports and only import dependencies that aren't already registered. This would not be a "production app" pattern, but in a "test harness" use case, a test harness could be refactored to support this relatively directly. I kind of felt managing a more nuanced registration check leant towards the "Going big" section in that we're talking about custom checks that we'd not only need to fully document, but would need to build the management of into our tooling. What would you like to see here to feel like we've clarified a path that was both approachable from a scale/usage point of view as well as maintainable long term? |
At the high-level, I sort of grieve the state of things. As a developer that works on SDK components, this makes it difficult for me to produce a module that contains SWC without it being extremely fragile. What I want to have is to provide multiple higher-order photography components, which use SWC, that you could include on your page via That being said, here's the check I think we should be doing. When a component is imported, instead of blinding registering, check to see if this exact version is already registered. We should be able to bake that in from the package.json, no? If a different version is already registered, throw a more meaningful message. |
Can you clarify whether throw means an actual error? Further, can you share what you think you want to see if version information is available? If an error is involved, I have a hard time seeing how extra information would be specifically more useful than the already registered error that would currently be thrown.
Gathering this information is slightly less complicated than gathering it at the right time. Currently we release versions via an alias to |
@cuberoot realized that a consuming applications can do something about this today, without any intervention from the library by monkey patching
Then you have full control over the shape, quality, and even presence of the messaging (which could be particularly useful to shape one way for your test set up and another way for you SDK deployments, etc.) to make it meaningful in your application and could theoretically inject is late, meaning at the beginning of your "second" application, rather than the beginning of everything, in that case that you didn't have full access to making changes at any one time. This, of course, doesn't touch on version inclusions, so there'd be no way, yet, to report on that, but it could be the sort of thing that allowed you to work out smaller local problems while we worked towards a large scale intervention a little later on. |
@Westbrook For spark post UI components we created a simple decorator & mixin, which is used for defining customElements. This decorator actually checks if element is already defined or not, if it already defined and exist on the page, it simply skips registration. example snippet looks something like below. Happy to go over if you want to discuss in detail. if (customElements.get(elementName)) return;
// define as custom element
window.customElements.define(elementName, targetClass, options); usage as decorator @defineElement({ elementName: COMP_NAME })
export class TheoComp extends BaseElement {} in Non-TS environments, we also added static method on our base element instance, if someone import component class as ES6 module and want to add own CE name, then consumers can do below. import { TheoComp } from '@package';
TheoComp.defineElement({ elementName: COMP_NAME }); |
Thanks for the above suggestion @Westbrook. I believe that one of the stated reasons for not checking if a component is registered before registering is to avoid a vulnerability where a false component with the same name is registered earlier. I believe that this work-around would also reopen that vulnerability 🙂. Basically, anyone that can register a component can do pretty much anything to your JavaScript context. I know that the other reason for not checking is because you want potential version mismatches to trigger an error. I don't mind doing the monkey patching for our own code in the short term. I am leery about monkey patching a 3rd party client's environment where our code is used. |
Great discussion - chiming in.. We had pretty much the same issue in the design system in our organization. For now we solved the issue via a different path: As long as you make sure that..
..you and up with a flat dependency 'tree' in your consuming application where you can swap individual components. Practically we have two ways to import a component:
This solution does not shoot for locally deviating versions of components but leads to one flat list of comps with the ability to switch some of them out. If you think about it, Sidenote: since npm 7 peer deps are actually installed automatically again which leads to a really transparent behavior of this approach regarding the install behavior. https://github.blog/2021-02-02-npm-7-is-now-generally-available/#peer-dependencies What do you think about this approach? |
Tracking this in #2666 |
This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
Expected Behaviour
I should be able to use SWC in two different javascript bundles from a single page.
Actual Behaviour
We get errors when
customElements.define
is called and I cannot see any way around it.Reproduce Scenario (including but not limited to)
Build two different code bundles that include SWC components. Try to load them into the same page.
Steps to Reproduce
Unpack the sample code below and then do:
Platform and Version
Sample Code that illustrates the problem
swc-collision.zip
Logs taken while reproducing problem
Console logs:
The text was updated successfully, but these errors were encountered: