From late 2018 to - at the time of this writing - 2022, I've found myself advocating and defending web components. This advocacy stems from framework fatigue induced by switching from jQuery to Sencha ExtJS to Angular to React to Svelte. For the most part, each framework has brought with it a DSL one needs to acquire to use effectively, but which is rendered obsolete when one begins working with a new framework.
Generally, a framework is collection of design patterns coupled with a means of enforcing them. If you've built your application right (think hexagonal architectures), you should be able to port your application from one framework to another without having to touch the majority of the codebase.
Web UI frameworks aren't like other frameworks because in addition to a collection of design patterns, they also provide a means of composing reusable widgets from atomic, native elements. This means of composition is unique to each framework, even when they have a common DSL like JSX. The uniqueness of each framework's composition mechanism means that widgets built in one framework cannot be ported to another.
Frameworks come and go, and on a platform that's evolving as quickly as the web browser, this is truer than most. The framework du jour might seem irreplaceable now, but at some point in the course of your project, you will run into limitations that have been solved by a newer framework. The limiting factor at that time becomes the cost of rebuilding your existing widgets for the new framework; try explaining to management why they need to fund, and allocate time for, the construction of UIs they already paid for. And even when they're willing, engineers can hardly be expected to be excited about the prospect of building the same UI again. Switching to a new framework this way is effectively a rewrite, and a rewrite brings with it the risk of recreating defects the team has already fixed.
So, understandably, management and engineering leadership express reticence at the prospect of a framework change. And as engineers struggle with fitting newer patterns into a framework that wasn't designed to support them, the quality of the codebase declines, leading to more defects and reduced team velocity. This in turn lowers confidence, which increases resistance to the idea of attempting a framework driven rewrite. The downward spiral continues until the cost of maintaining the codebase is judged equal to, or in excess of, that of rewriting the web application. The framework du jour is now eagerly embraced, and the cycle begins anew.
If one accepts that a framework change is inevitable (and perhaps even desirable) in a long living codebase, then a team's focus should be on minimizing the cost of a framework switch. Web Components offer a means to this end. They are a collection of four specifications (Custom Elements, Shadow DOM, ES Modules and HTML Templates) that collectively provide a means to building and deploying reusable widgets. A web component can be built once, and used across applications built with different frameworks. And because these are standards, they are less likely to be rendered obsolete, and are guaranteed to be supported across all modern web browsers.
While you can build components directly from the supporting Web APIs, you might find it productive to use a library that's been built to support this task. Lit and StencilJS are two of several libraries with acompanying tooling to help you build web components. And because they compile to the same 'target', they give you an additonal advantage: if you choose to switch web component libraries at some point in the future, you can make the switch for new components without having to rewrite the old ones, and use both in the same application.
References
- The Custom Element specification
- The Shadow DOM specification
- The ES Module specification
- The HTML Template specification
- Lit
- StencilJS
Top comments (4)
A few points:
Re. #1:
I don't know that I am arguing against DSLs per se, only that learning a new DSL for little gain in engineering capability resulted in framework fatigue for me.
There are cases where learning a new DSL grants you a superpower. I experienced this when learning RxJS, for example. But learning Angular wasn't a significant step forward for me after having used ExtJS. Svelte, on the other hand, was enough of an improvement that I'd never consider working with ExtJS again.
Re. #2 and #3:
I'd argue that portability here isn't about converting components from Lit to, say, Stencil, but rather about using Lit and Stencil components within the same application. When you decide you don't want to use a web component library anymore, it does not engender a rewrite of those components you already built.
Also, portability is very much a developer experience problem from my point of view. I would never voluntarily undertake to work with ExtJS again, unless I was getting paid 10x of what I'd charge for working with a more modern framework.
Re. #4:
That's true, but I was speaking strictly in the context of web applications. My argument dos not take cross platform portability into account.
You almost scored a +1
But then you mentioned Lit and StencilJS
There are now over 50 of these BaseClasses available.
Where you say Frameworks come and go, are you really of the opinion all these BaseClasses will have a future?
They don't have to.
When you decide to switch from one web component library to another, you don't have to rebuild the components you already have; you can use components built with the old library and the new one without real challenges. Regardless of what base classes a library may use, the end result is a web component that adheres to a spec.
Like frameworks, I expect web component tooling to come and go, but because they're spec-compliant, you should be able to use them in a new application long after they are no longer updated.