loading...

The journey of Web Components: wrong ways, lacking parts and promising paths

webpadawan profile image Serhii Kulykov ・9 min read

In my previous blog post about Web Components, I described several challenging problems still unsolved as of today. The feedback I received was surprisingly warm, and I was feeling excited to be mentioned by Alex Russell, one of the authors of the initial proposals. Some people called my notes a bit of an eye opener, while others mentioned even more problems.

Taking pink glasses off wasn’t the only goal I wanted to achieve though. My criticism was aiming to identify the pain points, and remind about the importance of consensus. The recent blog post by Jan Miksovsky about the history of HTML <slot> element is a great illustration of the dead end where we could get same as 5 years ago, by pushing the proposals again.

Today I would like to expand my vision further and approach the same topic from a slightly different angle, by exploring the journey of Web Components towards the adoption so far and in foreseeable future. Same as previously, I rely on my personal experience and observations, so feel free to add your own notes, and correct me if you think I’m missing something crucial.

One more thing from the previous post I would like to remind you about is the upcoming “Face to face” (F2F) meeting regarding Web Components, with the participation of spec authors, browser vendors and users. Yes, there is a slot in the agenda dedicated to the real use cases. That’s good news, and I’m looking forward to see the meeting notes once they are published.

The wrong ways

In early 2016, when I was making first steps with Web Components, there wasn’t that much examples. For me, the only source of inspiration at that time was Polymer Starter Kit. It has been changed a lot since then, and was replaced with the LitElement-based successor, PWA Starter Kit. But in a nutshell, they do the same: place <my-app> component in index.html.

Wrapping a whole SPA into web component is the point where some people start to dream about throwing the frameworks away. At this very moment, in my opinion, they start falling into the pit of using improper patterns. Here I share the concern raised by Mattia Astorino. And from my previous post you already know how overusing Shadow DOM might strike back.

Taking the story further, the common feature every SPA needs is a client-side routing. And yes, people have been using Web Components for routing, too. In my former team, we were using <app-router>, a vanilla v0 custom element from 2014 – and one of the first open source projects I ever have contributed to. At that time, I really liked its way of declarative routing.

But today it sounds ridiculous to me: first we run JS while registering a custom element, then each time user navigates we search matching routes from the DOM and run JS again. Am I wrong or is there an extra link in the chain? Declarativity is good per se, but trying to use HTML anywhere you need it, or in a way other people use JSX, is again a serious mistake.

The next framework-specific wheel we had to reinvent was a set of tools for loading data and managing application state. There has been a lack of best practices in this area in Polymer community. In short, we were supposed to use <iron-ajax> to trigger API requests from the DOM, and then store the data again in the DOM – just to completely mess things up.

Someone would say, once you get locked into a web components collection, the tendency is to push it as far as you can. It can be explained by the fact that Polymer was heavily limited by HTML Imports (thanks to Mozilla for dropping them), and based on some assumptions from the “model driven views” concept, inspired by the dream about "declarative renaissance".

Talking about HTML, there is still a chance that HTML modules proposal will improve our developer experience and allow to use <template> more. This is one of the areas where the Edge team is doing contributions to Chromium. While this could help creating Web Components in a better way, we shouldn't take those wrong ways of using them anymore.

The lacking parts

Back to 2019, what are the better use cases for Web Components today? The first one you probably thought about are UI components, especially complex form controls. Surprisingly, Custom Elements are not currently designed to be picked up when submitting the standard <form> HTML element. The form participation API proposal by Chrome team is expected to fix that.

When looking at the list of proposed updates to Custom Elements API, it seems to be a lot of work for browser vendors to agree and implement. Until then, we are unable use HTML form validation and submission without workarounds like <iron-form> element. In my opinion, Web Components could reach a lot more audience once this issue is finally solved.

There are few other problems related to using Web Components in forms. One of those is broken form autofill for form elements within shadow trees in Safari. Another issue is that password managers like LastPass or 1Password do not support <input> elements in Shadow DOM, as they presumably rely on global API, like document.querySelector().

One more Shadow DOM concern we need to keep in mind is how it affects accessibility. This was described by Rob Dodson, but let me repeat in two words: shadow trees introduce the boundaries for IDs in the document, which affects ARIA attributes, like aria-labelledby. That can sometimes make it harder to make the components both accessible and granular.

The similar issue with the IDs breaks the internal references in SVG, when using it inside Shadow DOM. As an example, <use> element doesn’t work because of how href references are resolved. Good news is that at least Safari has a solution supposed to fix that particular bug – which still has to be adopted by all the other browser vendors and then reflected in standards.

As you can see, at least two seemingly perfect cases to be solved with Web Components – namely, form elements and icons – have been more or less blocked for a while. In my opinion, having such lacking parts not covered for years (including the issues I already mentioned in my previous post) hurts the expansion of the new standards more than anything else.

The promising paths

So how could Web Components eventually reach the adoption? The browser support (at least, for basics) is now good. What we really lack today are real examples of using the native component model in production – preferably, in the big projects – and the best practices as a logical outcome of those. This in turn leads to a lack of trust to Web Components, and so on in a circle.

There is of course an example of YouTube, which is again a full SPA built with Polymer. But so far we observed mostly complaints about it being slow in Firefox and Edge and causing the decision to postpone the removal of V0 specs until Chrome 75. Finally, YouTube still doesn’t use native Shadow DOM, but a polyfill (and will most likely continue doing that in future).

Another case I would like to highlight is GitHub, which switched to using Custom Elements as part of the effort related to moving away from jQuery. What is especially great is how well Custom Elements fit the idea of keeping the content in HTML and progressive enhancement. See details-dialog and details-menu elements as really good examples of that philosophy.

Moving forward in search for the hype train where Web Components could in theory jump in, it appears that the today's motto are design systems. Reusability and being framework agnostic are the strengths we shouldn’t underestimate; that’s why Tesla has chosen Web Components. We shall see over time how much people consider making the same bet.

Enterprise companies are potentially the strongest audience for Web Components, and that’s what we see from State of JS 2018 survey – check the numbers for Polymer. Let me mention ING and its team of open source enthusiasts who created open-wc, and Red Hat sponsoring the PatternFly elements library among the examples of such big companies.

One of the promising paths would be using Web Components to build an architecture and to embed parts of the application. This concept is known under the name of Micro Frontends. It can be questionable to what extent should we use Custom Elements as “spicy iframes”. But at least it’s good to keep in mind that DOM and CSS aren’t necessarily global anymore.

What's next?

Back to where we started, let me again emphasize that Web Components are not a silver bullet. They will not replace JS frameworks, despite some people claim the opposite, or even start saying bye to React. In fact, such biased statements usually hurt more than help. That's why I wanted to add my 5 cents to the ongoing discussion and drive it in the right direction.

The Web Components are safe to use today, regardless of all the unsolved issues requiring further standardization, which I have tried to systematize. Forewarned is forearmed, and I hope you are brave enough to not even fear the Chrome crashes or rendering issues, which have affected few stable versions. Some things need to stabilise, but it’s not that scary after all.

The lack of expertise among the developers, admitted by David Flanagan during the recent holy war regarding the MDN web docs page header being rewritten in React, doesn’t sound a really valid excuse to me either. As long as most of frontend teams stick to well known stack, how would we adopt for example CSS grid layout, or ES modules supported natively as well?

So let’s accept the challenge and take it as a chance to be a pioneer, building completely new things with the native component model which the web platform offers. Now in 2019, it’s time to give a try to Custom Elements and Shadow DOM. They might not be “the next big thing” by themselves, but rather solid foundation the next big thing could be built upon.

I recommend considering Custom Elements, Shadow DOM or both, depending on the actual needs, when starting a new project or refactoring the existing one, to anyone interested in the long-term solution. Also, I would love to hear about the lessons you learned with Web Components – including your own pain points, as I realise that it’s not all roses.

Finally, I would like to encourage anyone to contribute to the “awesome” list named Web Components: the right way. As I previously announced, I’m the maintainer of that project and try to do my best in order to make it a more or less full and up-to-date knowledge base. And, as usual, I’m very grateful to hear your feedback and any comments regarding this blog post.

Posted on by:

webpadawan profile

Serhii Kulykov

@webpadawan

JavaScript developer and open source enthusiast, building Web Components at Vaadin (previously at OWOX).

Discussion

pic
Editor guide
 

I tried to use Web Components on my most recent project and failed miserably. Legacy systems was probably the biggest thing holding me back, as I had to support IE11 and not all component libraries were able to provide that support through polyfills, so I sat there confused, trying to figure out the differences between a dozen libraries I had never heard of, and attempting to do some tutorials with each to get a feel for what would work out well.

I was really interested in Svelte, but I haven't ever used Typescript before and that became enough of an issue that I had to choose something else. The site I was making the components for is built off of ASP.NET Web Forms, so it was really difficult to bootstrap data into the pages and I couldn't figure out a reliable build system for my components. I gave up and went back to the site's default jQuery approach because I couldn't waste any more time pllaying around with things. If I had to do it again, I would probably just use Vue with multiple roots instantiated on the page.

At my next job, I won't be stuck with as many legacy systems, but I will be switching to a mainly-backend role and won't have much sway with the front-end team, who is all about React. I see value in Web Components, but I don't have enough experience to validate any of my points. I wasn't able to make any production-grade examples which demonstrated the value of Web Components, in fact, I wasted hours and hours frustrating the hell out of myself.

There were too many options available and I felt overwhelmed. Most of the options provide poor documentation, or none at all. There didn't seem to be a solid community I could rely on if I had questions and overall I got a sense that there wasn't a lot of knowledge to be passed around. I have some time off until my new job begins and I considered looking into Web Components during this time, but it was such a frustrating experience I don't want to re-approach the issue. I think I might learn Haxe or ReasonML instead.

 

Thanks for the feedback! As I mentioned, the lack of documentation and best practices is the key, and might become a blocker for many teams. That's why I have started working on "Web Components the Right Way" project.

Svelte and probably other similar "disappearing frameworks" might get attraction once they stabilise and provide clear documentation and smooth developer experience. The popularity which Vue gained is a great illustration.

Hopefully React will gradually update its internals (at least the project announced as "React Fire" sounds promising) to be more compatible with usage of native DOM APIs, but I don't have enough context to make any statements on that.

 

That's a noble effort. I'm curious about your project, it sounds really cool. Is there anything I could help out with? I'd really love to learn how to do this right and I can see it being something to advocate for at my new job. I will mostly doing backend so it would be cool to have a connection to FE still.

Thanks for the feedback! At the moment, the list contains a bunch of links to specs, various articles and tutorials, etc. Feel free to hare any feedback on the structure, order of sections or anything that would help to make it more clear and easy to use by newcomers.

 

Hi, Scott!

I was really interested in Svelte, but I haven't ever used Typescript before and that became enough of an issue that I had to choose something else.

Could you please describe a little bit how exactly Typescript was affected you to use Svelte? Actually, Svelte doesn't support Typescript at all for now.

 

My bad, I meant to say Stencil. Trying to get a grasp on the concepts behind web components takes a lot of brain cycles for me right now...they make total sense to me and a componentized architecture with communication visa a message bus is how I have been designing Javascript for years. So I understand what they are supposed to accomplish and it excites me, but I have a very informal definition of building components over the years vs doing it in a standardized way. Hand coding components just takes a really long time, so I felt like I would be wasting time if I didn't go with one of these support libraries. Typescript was just one thing more to have to remember on top of everything else, it was information overload and I was super-stressed out already.

I also think it might have been a much better ending to the story if I wasn't working with an ASP.NET Web Forms-based CMS. There is 0 info out there on getting Webpack set up in Web Forms, and it is something I struggle to do in a modern environment already. This project was the breaking point where I realized there was so much technical debt in this company's website that making any productive, major changes was going to be near impossible. It was built by an "expert" agency before I was hired and it was some of the worst code I have ever seen, so glad they "accepted my resignation early" and let me go.

I'd be curious to see them work out on a project I don't actively dread working on.

Oh, I see, everything fell into place. So, I definitely advise you to try Svelte. It has pure and neat syntax and a bunch of built-in features under the hood. Shows us great benchmarks metrics and can be compiled as native Web Component by setting a single flag in compiler options. Check out this video for a quick overview: youtube.com/watch?v=Gne762oc7s4

 

Try hyperapp. Its a 1kb alternative to vue.

 

I'm proud to be able to say that Aurelia has been leveraging the WebComponents HTMLTemplateElement, ShadowDOM, and Slot capabilities since the framework was conceived in late 2014. We've worked really hard to leverage standards and then augment them with the pieces needed to create more complex applications. We're not as well-known or as large as something like React, but we've still got tens of thousands of companies building with Aurelia who are very happy with our approach to adopting standards in this way. Just a couple of weeks ago, we introduced a plugin that enables our components to be exported as WC Custom Elements, with no additional work by Aurelia developers. We're carrying this work forward with our next major framework version, leaning even more on these and emerging standards and making them even easier for people to leverage.

Thank you Serhii for the honest and balanced look at Web Components. Speaking for my team, I can say that we're very happy to see that more real use cases are being discussed and that there's action around several of the most critical long-standing issues. If I or anyone from my team can be of service in helping to advance this work, please don't hesitate to reach out.

 

These posts are awesome, please keep them coming.

Is love to hear more from you on why you think <app-router> was a mistake. I really enjoyed using it back then, and I've often heard how the concept was "wrong", but I'm still curious why it is considered such a harmful pattern.

Nowadays I do my routing in callback methods in <my-app> type elements, or I use a data framework like Apollo.

 

The problem as I see it lies in choosing improper abstraction.

There is no need for such components to be in the DOM, and to query from the DOM just because we consider HTML as the only way of writing declarative code in the applications we build.

I still think that DOM should only contain the "view" layer, whereas router is better to have as JS library not necessarily tightly coupled with web components.

 

Thanks for the explanation. Do you think that having that model code in the DOM was error prone or insecure, or is it strictly a matter of separation of concerns?

I think both statements are valid to some extent.

Storing data (especially, when it comes to application state) in DOM is one problem, attempting to use DOM for meta programming is a different one.

Interestingly, trying to solve the first problem could sometimes result in leaning towards the second one, as we can see it when looking at github.com/google/uniflow-polymer

In my opinion, all these problems have been implied by the two way data binding system and how it affected the way of thinking of Polymer users.

 

I hold a lot of hope for Web Components, and right now I am in the process of aligning a massive platform front-end refactor; so far I cannot outweigh the risks (functionality and performance blockers and knowledge among devs) with the benefits of using Vue.js.

With that said, trying to align with a Web Component approach is still highly desirable. For us, the "tipping point" of community support and shared knowledge with a solid, single direction would allow us to adopt this tech. So, we won't be rendering an all-containing <my-app>, we will have many roots instead. We also considered the approach noted here, allowing a path to migrating away from Vue.js in the future, as WCs mature - but as you can see from those docs, IE11 is not supported. This is a deal-breaker for us, as are accessibility shortcomings, so the benefits of adoption get watered down more.

In the long term, our team will look to align as closely as we can to properly composable concepts with HTML because it feels right. We hope in the future to adopt a WC standard and approach to not only individual components, but also collections of those components, right up to whole page layout level (we follow atomic design principles, for example, and I can foresee WCs being a solution for all levels of it).

In the short term however, battling through adoption blockers and issues would strain our resourcing and probably introduce issue for end users; both of those things affect our business bottom line, so we must play it "safe".

 

Thanks for the feedback! I like your idea about how the atomic design principles might work with Web Components.

It's unfortunate that IE11 is still a blocker for many projects. Hopefully, Chromium-based Edge delivered to Windows 7 and 8 will help to slightly reduce IE11 usage under 5% where it still stays. Until then, there are polyfills, but using them results in not so graceful degradation as we'd want it to be.

 

Just came across your post and i am very into the whole Web Component topic. I am currently writing my Master Thesis about a "Declarative Shadow Root" solution to provide HTML authors with the same encapsulation features JS developers have with Web Components. Do you have an opinion on that topic as well?

 

We have recently started a POC for using LitElement for our huge enterprise Web app. One problem, I am facing initially tooling wise is Chrome Dev tool's inability to alter CSS within shadow Root on the fly.

Its really helpful to be able to experiment with CSS right in the browser, with Web Components that flexibility seems to be taken away which I think is a bummer. And this one for a change does not require browser consensus :)

 

There is an issue to fix that already so I hope it would be resolved in future:
bugs.chromium.org/p/chromium/issue...

In the meanwhile, you can workaround that using delete Document.prototype.adoptedStyleSheets.

When called prior to loading LitElement, this will make it act like the feature does not exist and place style elements into the shadowRoot (same as Firefox and Safari).

 

It's a great post. I enjoy reading it especially the slot proposal. BTW, I spotted a typo in the What's Next section: event start -> even start.

 

Thanks a lot! Thanks, fixed the typo.