[AskJS] WebComponents and version management

Consider this scenario fellow redditors:

My application uses two React Components, ListOfSheep and ListOfCows which both have a dependency on ListOfAnimals. Though, due to evolving requirements, ListOfSheep requires ListOfAnimals 1.2 and ListOfCows requires LitsOfAnimals 2.1 - which is a breaking change!

While it would be ideal to not use two different versions of the same components, it is also no biggie: no matter which package manager I use, this case is handled - each component can require the version they need, and this scenario doesn't cause any problems. Maintainers of Cow module can bump their version to suit their needs, without worrying about breaking Sheep module code and the whole case ends with an email note to the other team "hey, maybe you should bump your version of ListOfAnimals, it is quite old".

Now, the same scenario usig WebComponets ends with one of the modules (the one loading later) throwing exception

Failed to execute 'define' on 'CustomElementRegistry': the name "list-of-animals" has already been used with this registry

that you can't really even recover from.

For those unfamiliar with CustomElements, they need to be registered with a global name. Yes.

Does anyone here have some experience working with WebComponents at at least moderate scale (i.e. application large enough to be maintained by largely separate teams that enjoy (and often need) working as independently as possible) and maybe has some tips how to handle such scenario in app using WebComponents?

I'm also interested in your opinions about WebComponents standard - I can hardly believe that the standard that is supposed to be "the future" is implemeted in a way that basically requires you to use global variables (or rather global names, but well, same problems). Is the standard really poorly thought out, or am I missing something?

It seems silly to me that a case that is basically a non-issue when using React is such a PITA when using WebComponents.

8 comments · 86% upvoted · other discussions

comments

DrunkenKnight_

Not discussing whether or not having several versions of the same component is good or bad: https://github.com/w3c/webcomponents/issues/716 this is what you're looking for, although as you can see it's still only a proposal

At the moment you have to make sure everyone uses the same version of the comp or introduce an "always backward compatible" policy within your org and force everyone on latest

Src: worked in large scale orgs with web components for a few years

yerrabam

Monkey patch it or make your parent class more abstract.

e111077

Until scoped element registries are a thing, you should separate where you call customElements.define from where you define the element base class.

Thus you can have list-of-animals and list-of-animals-old

If you're doing a version migration, see if you can shove all the new features into the same element behind a flag, then incrementally add those flags and migrate your app to the new version piecemeal. Then make the new one the default and remove the flags.

If there is no plan to migrate, the real issue, again, is duplicated dependencies. This is why larger companies tend to converge on monorepositories since the bloat just grows with more teams.

azsqueeze

To me it seems like the problem is with your architecture rather than the WebComponent API. The fact that you need two separate versions of the same dependancy sounds like a "code smell" and should be resolved first.

Also remember WebComponents is a way for your JS to read a custom element added to the DOM. When you take that into consideration it makes sense why they're on a global namespace. Imagine if you tried to select a <div> with JS but each <div> you get back has a different meaning, api, etc. That's what you're suggesting.

braindeadTank [OP]

As I noted, it would be ideal to never have two separate versions of the same component.

But if you have multiple teams working on the same app it's just not really a viable approach if you want to keep delivering quickly. It is much better to allow each team to handle their dependencies separately on sprint-by-sprint basis and only align periodicaly to prevent too much code bloat. It is less about architecture and code smells, and more about work organisation.

Also remember WebComponents is a way for your JS to read a custom element added to the DOM. When you take that into consideration it makes sense why they're on a global namespace. Imagine if you tried to select a <div> with JS but each <div> you get back has a different meaning, api, etc. That's what you're suggesting.

3rd party solutions don't have this problem, so clearly another design was possible.

vidarc

I'm going to have to deal with this soonish. Our main UI components are web components, while the rest is a micro frontend setup where you could have several apps per page (maybe even frameworks as well). My current idea is to handle it with a Babel plugin. Each app specifies their UI component library version, then the Babel plugin just appends that. They would still use some-button, but after build it would be some-button-1-1-0.

Im not super happy with a lot of what we're doing, but it's pretty much all due to non tech reasons why we are doing what we're doing. Haven't actually gotten around to trying it out yet though. We currently just load it globally and try and not break anybody.

DaveSims

This is one of several reasons why web components should be used sparingly to create custom DOM elements and should not be used to try to build a complete application.