
Making Web Components Work - tdumitrescu
https://engineering.mixpanel.com/2018/06/12/making-web-components-work/
======
aphextron
I've been using web components in production for a while now and it's great.
Our front end "stack" consists of a single polyfill and Webpack. Use template
literals for templating, so you don't even need handlebars/mustache anymore.
Webpack lets you write SASS that is compiled directly to CSS and inserted in
your shadow DOM with an ES6 import, so no more style sheets for anything but
high level page layout. Everything is standards based web components written
in vanilla ES6, transpiled for browser compatibility down to IE10.

One major issue we've had though, which wasn't touched in this article, is
inter-component communication among siblings. Sure you can just do a global
event bus, and that works, but I've yet to see an elegant solution for this
yet.

~~~
interlocutor
_> > Use template literals for templating, so you don't even need
handlebars/mustache anymore._

You can do better than template literals. You can use TSX, which gives you
compile-time verification for tags and attributes, in addition to JavaScript
expressions.

See:
[https://github.com/wisercoder/uibuilder](https://github.com/wisercoder/uibuilder)

With TSX (which is JSX written using TypeScript, you get things like syntax
coloring and indentation for tags, because HTML and JavaScript are both first-
class citizens in TSX.

~~~
_sdegutis
I’ve only been using React for a few weeks but the comparisons on that page to
React are FUD and the incompatibility with web components is just plain wrong
and mixing them is covered here [https://reactjs.org/docs/web-
components.html](https://reactjs.org/docs/web-components.html)

~~~
petilon
From the page you linked: "Events emitted by a Web Component may not properly
propagate through a React render tree."

React components are brittle, that's not FUD. For example, CSS classes used by
React components can clash with other React components, or with the page that
includes them. What's FUD about that?

~~~
TomMarius
That's misunderstandong of the technology. React has nothing to do with
styles, it manipulates DOM. Handling styles is up to you, and it's extremely
easy to use CSS modules.

~~~
krishanath
_> > React has nothing to do with styles_

That's one of its limitations.

React is a component technology and doesn't solve the problem of clashing
styles, element ids and so on. Web components is a component technology that
does.

~~~
TomMarius
No, it's not a limitation, it's called separation of concerns, I don't want my
component framework interfering with the job of Webpack or application
runtime. I want to use my preferred (also easy, standard, ...) solution.

> clashing IDs

React solves that one, not through namespacing though. You never need to use
IDs with React.

> clashing styles

React gives you power to solve this one by your preferred solution. You can
use expressions in your JSX, and thus it's very easy to do one of the
following:

\- Generate optimal global CSS stylesheet with no code repetition, generate
classnames on the fly
([https://github.com/typestyle/typestyle](https://github.com/typestyle/typestyle))

\- Import your CSS file as a module using Webpack - classnames are guaranteed
to be unique; additionally, similar approach as TypeStyle (global optimal
stylesheet) can be set up

\- Use just "inline" styles (preferably not really inlined in your JSX) since
React will keep it updated for you as well

~~~
anthonybullard
>You never need to use IDs with React.

If you don't care about accessibility then yes.l, but try using properly
annotated aria attributes without appropriately scoped ids(which you can do in
react, but it's not free).

~~~
TomMarius
Hmm, right now I truly don't (that's the business requirement :-/). I'll
investigate, thank you.

------
beders
I still find it bizarre that no one has stated the obvious yet:

Having a component tree (because the rendering model of a browser requires it)
does not mean state management needs to be cramped into the same tree or use a
tree in the first place!

A DOM tree itself doesn't do any kind of binding and it doesn't do inter-
component communication. (it merely offers events) Why should web components?
Keep them as dumb as DOM nodes please.

A lone H1 element doesn't register itself on some event bus, doesn't observe
attribute changes and doesn't create odd 'actions' tied to some obscure state
management system. And it shouldn't.

~~~
yayana
I only recently started looking at upgrading from angularjs to angular and web
components were one of the things that made me question the emporer's
clothes..

Zone js implements zones and by that they apparently mean exactly 1 zone..
making a supposed abstraction where you can't safely add 2 implementations of
web components (or apps?) to 1 page without planning for that with 1 global
setup for them..

My initial impression of shadow DOM is that I would get the same scope
separation as iframes with a nicer method of passing data and describing the
layout.. Then I assumed web components were this missing piece finally
implemented.. now I'm wondering if I completely misjudged and everyone else
really wanted a complicated footgun where seeming builtins are colliding with
your namespace?

------
stupidcar
For me, the biggest plus of web components is the potential simplicity of
unifying the document's object model with that of your application. Every JS
framework, like React, Angular, Vue, etc. seems to have a parallel OM that
either wraps or renders into the DOM (Angular seems to have about 5 of them).

The result is your can never just use the basic DOM APIs and devtools to
inspect and interact with your application's components. Instead, you always
have to get at them through some other API, and understand how the UI and
state you see in the DOM is produced and updated by some mediating layer
(virtual DOM, view hierarchy, etc.). It feels like trying to get at the truth
by talking with two different people, who each only possess a subset of the
facts.

~~~
derefr
These layers were created for efficiency, not for their own sake; there’s no
“DOM transaction API”, so every DOM mutation causes a reflow. Thus, you mutate
a virtual DOM, render the resulting changes to a new subdocument, and then
replace an existing DOM node with that new subdocument.

~~~
stupidcar
Incorrect. This idea was a result of some early React users misunderstanding
the purpose of the virtual DOM, and has unfortunately been thoughtlessly
repeated ever since.

In reality, browser engineers are not that stupid. Mutating the DOM will queue
a layout operation, but it will not actually occur until the current JS task
has finished executing. Within a JS task, such as an event handler, an XHR
completion, or a setTimeout, you can mutate the DOM as many times as you like,
and it will only result in a single layout pass.

(The exception is if you try to read back some measurement from the DOM, such
as an element's bounding box, after mutating it. In this case, the browser
does have to block while it performs layout, but that is not something can be
solved with virtual DOM).

So, what is the purpose of the virtual DOM? It was invented to allow React to
provide the illusion of full re-rendering. React's authors wanted to a provide
an experience similar to that found on the server, where an entire HTML page
is re-rendered from scratch for every load. In that way, there is never any
possibility of part of the HTML becoming stale, as it all gets recreated from
scratch each time.

However, the browser DOM is not designed to be blown away and recreated from
scratch all the time. Nodes are expensive objects, spanning the JS and C++
worlds. Recreating the whole DOM tree each time any part of it needed updating
would be too slow. So, instead, they created the virtual DOM as an
intermediate data structure. React renders the virtual DOM. The virtual DOM is
diffed against its previous state, and then the changes are applied to the
actual DOM tree. In that way, every component's render() method can be
executed, but only those parts of the DOM that have actually changed will be
updated.

It's a nifty optimisation, but it's not about avoiding reflow, it's just
another method of dirty checking, similar to that done in other frameworks
like Angular or Ember. It's just that React chooses to diff the data structure
produced by render(), rather than diffing the model data that is later used
for rendering.

~~~
dmitriid
Please read this blog post titled "How to win in Web Framework Benchmarks"
[https://medium.com/@localvoid/how-to-win-in-web-framework-
be...](https://medium.com/@localvoid/how-to-win-in-web-framework-
benchmarks-8bc31af76ce7)

It goes into some details how different approaches in different frameworks
work, and why. Moreover, it shows how you basically need to re-implement
Virtual DOM and other tricks in vanilla JS code to approach the same speed.

Yes, browser engineers are not that stupid. But they don't batch operations as
efficiently as a proper Virtual DOM implementation would (including
efficiently handling event listeners, looking for clues like `keys` on
repeating DOM elements etc. etc.).

~~~
stupidcar
That article doesn't quite support what you're claiming. The Vanilla JS
implementation uses optimised DOM mutation techniques that are inspired by how
the Virtual DOM libraries do things, but it doesn't re-implement a Virtual
DOM. Yet it's faster than any of the Virtual DOM implementations its
benchmarked against.

So the takeaway is that DOM mutation can be slower or faster depending on the
techniques you use. Using a Virtual DOM library can help you improve
performance, because these techniques are often baked in, but they don't
intrinsically result from using a Virtual DOM: You could write a V-DOM library
that didn't use them, and was slow, and you could write, for example, a static
template library that did, and was fast.

In theory, a compiled, static template approach should be faster than V-DOM
(or anything other than a set of totally bespoke and optimised vanilla JS
functions for each app operation). Because while a compiled template does not
have the turing-complete flexibility of something like JSX, it has the
advantage of knowing in advance exactly which parts of the DOM can change and
how, which eliminates the need to build and diff the Virtual DOM tree.

~~~
localvoid
> In theory, a compiled, static template approach should be faster than V-DOM

Maybe faster in basic microbenchmarks. As soon as you start optimizing UI
library for complex applications, there are many other optimization goals you
should focus on, like the size of the generated code per component type, the
amount of different code paths(increase probability that executed code is
JITed), etc.

Virtual DOM solves many issues, it is not just diffing, it is also a
lightweight component model, possibility to add lightweight synthetic events,
single code path for creating/updating/destroying DOM nodes, the simplest algo
that handles complex tree transformations, etc.

------
russellbeattie
I just started using Web Components, and in my opinion, their future is
definitely very bright. Now that HTML imports have been squashed, they're
basically just standard JavaScript objects imported as modules, as they should
be. Before, you created a class/object that had a property like foo.el which
was the element it was associated with, but the link was tenuous, and required
a bunch of code to keep things in sync, and various component styles could
easily clash. Extending native elements and the Shadow DOM is a great way to
contain everything. Wiring them up to something like Redux or MobX is trivial.

The only real missing piece is the concept of props over attributes. If I want
to pass an array of ids to a sub-component declaratively, there's not really
an easy way to do it. Hopefully there will be some consensus about this soon.
The best thing is that this is all part of modern browsers without libraries,
or even precompilation. Not every web app needs massive libraries, so having
web components as a built-in, light-weight component system is fantastic.

~~~
interlocutor
_> > If I want to pass an array of ids to a sub-component declaratively,
there's not really an easy way to do it._

Yes, there is. See
[https://github.com/wisercoder/uibuilder](https://github.com/wisercoder/uibuilder)

~~~
russellbeattie
Err, no. What part of that mass of crazy non-JavaScript did you think was
"easy"? Wow. I didn't even know TSX was a thing. To each his own, but yet
another dependency written in indecipherable pseudo-script (regardless of its
popularity) is not my idea of easy.

------
kruhft
Web Components were interesting but too complicated and never gained traction
at Autodesk (my former employer) where we just ended up going with React,
which is actually a pretty good solution to the crappy ecosystem that browser
based programming has become.

------
k__
I read Polymer is switching to JS modules with 3.0, sounds like a right step
for Web Components :)

~~~
spankalee
We already did :)

------
jacob019
Just started using Vue.js and the components approach makes a lot of sense.
Web Components is a not-quite-ready pure JS approach? Vue, polymer, react
native... I feel confused every time I read "Web Components" because it means
something different depending on context.

~~~
spankalee
Web Components means the standards of <template>, Custom Elements, and Shadow
DOM. There's an overview here: [https://developer.mozilla.org/en-
US/docs/Web/Web_Components](https://developer.mozilla.org/en-
US/docs/Web/Web_Components)

Polymer has always been a set of helpers for making Web Components. There are
others like SkateJS and Stencil.

Vue is not normally Web Components, but they have an option in CLI 3 to
compile to Web Components.

React and React native have basically nothing to do with Web Components,
though React can use Web Components because Web Components are just HTML
elements.

~~~
dmitriid
> Web Components are just HTML elements.

Yup. And you can't use Polymer elements in React because React passes data as
attributes whereas Polymer expects properties.

And then there's the issue of event handlers etc. etc. etc.

"Web Components" are now a largely non-intersecting collection of mutually
incompatible frameworks and libs: [https://custom-elements-
everywhere.com](https://custom-elements-everywhere.com)

Good luck using Polymer's <custom-element binding="{{a.b}}"> anywhere

~~~
spankalee
> And you can't use Polymer elements in React because React passes data as
> attributes whereas Polymer expects properties

This is mostly React's existing opinion that elements don't even need
properties set, and is not the fault of Polymer or Web Components. Most
Polymer elements are fine with simple types like strings or numbers being set
as properties or attributes.

> "Web Components" are now a largely non-intersecting collection of mutually
> incompatible frameworks and libs: [https://custom-elements-
> everywhere.com](https://custom-elements-everywhere.com)

That is a site that says how well _frameworks_ work with Custom Elements, ie
do they make closed-world assumptions about HTML that interfere with using
Custom Elements. It says nothing much about what a Web Component is, so I'm
not sure how Web Components could be "non-intersecting".

> Good luck using Polymer's <custom-element binding="{{a.b}}"> anywhere

I know you troll every Web Components and Polymer discussion you can now, but
this is just a non-sequitur. Polymer's template syntax is only used to
implement elements with Polymer. `<custom-element binding="{{a.b}}">` would
only ever occur in a Polymer template and is not intended to be used
"everywhere", so no luck is needed, thank you.

~~~
dmitriid
> I know you troll every Web Components and Polymer discussion you can now

This is not trolling. This is called hard truths that Web Component proponents
are completely blind to.

Riddle me this: why is it that there are almost no resources, blog posts,
projects, or comments that talk about and use vanilla Web Components? 99.9% of
posts and videos about WebComponents always immediately use Polymer, or
Stencil, or... or... or...

The answer is easy: Web Components are crap, pure and simple. They are
unusable in their present form. You need to throw in a data binding library, a
templating library, a virtual DOM, a callback handling library, a..., a...
etc. Better still, throw in a full framework like Polymer or Angular.

Even the project we're commenting on, titled "Making Web Components Work"
needs the following to make them work: "does so by providing an easy-to-use
state management and rendering layer built on Virtual DOM (the basis of the
core rendering technology of React). Through use of the Snabbdom Virtual DOM
library and first-class support for multiple templating formats".

How the hell is that "Web Components", "standards" and "work"?

When you call out all these inconsistencies, half-truths and outright lies
about Web Components, you're called a troll, go figure.

\---

As an aside. I remember saying that templating in Web Components is also crap
because you have to use horrible DOM APIs or `innerHTML` to do anything
useful. Obviously I was called a troll etc. However, when Apple proposed
Mustache-like template instantiation [1] the same very people who called me a
troll pissed themselves with joy and wonder. You _know_ Web Components APIs
and specs are crap. You chose to bury your head in the sand, turn a blind eye
and preach how "WebComponents are the future". Well, it took browsers 11 years
to get to two-thirds of jQuery's capabilities. It will take another 50 to
maybe get one-third of capabilities of Web Component frameworks or React, or
Angular, or Vue (hell, of even Snabbdom).

[1] [https://github.com/w3c/webcomponents/blob/gh-
pages/proposals...](https://github.com/w3c/webcomponents/blob/gh-
pages/proposals/Template-Instantiation.md)

------
mikece
I think the next major leap forward in HTML app development will happen when
Web Components are portable across client framework types so it's not
necessary to rewrite every visual element when switching from Angular6 to Vue
or even something compiled to WASM in a few years.

~~~
spankalee
This is exactly what Web Components already do. Web Components are just HTML
elements, and generally usable in any framework or with no framework.

~~~
mikece
Oh -- awesome! I've been focused on back-end and mobile the past few years. I
guess it's time to dive into Web Components!

~~~
themacguffinman
Check out [https://www.webcomponents.org/](https://www.webcomponents.org/)

------
westoque
Off topic.

Not to be harse. But for a company as big as Mixpanel, the blog UI is
terrible. No branding at all and seems unprofessional.

Even more ironic is they say this as the first line in the post: "Clean,
attractive user interfaces and effective user experience have always been
pillars of Mixpanel’s products."

They should look at companies like GitHub, Facebook, Twitter, and the likes
for an example.

~~~
polartx
You _are_ looking at the engineering blog, which--judging by the rest of the
mixpanel.com site, probably isn't borrowing much from the marketing/ux side of
the company.

Check the Mixpanel blog
([https://mixpanel.com/blog/](https://mixpanel.com/blog/)) and you'll find it
the brand consistency more similar to the other tech companies you mentioned.

I'm actually okay with engineers spending less time on shiny css and more time
on the content of their posts.

------
justrobert
One thing their example doesn't handle is browser location history on clicking
elements in their UI.

Maybe it was due to how simple the example was, but having to click back many
times based on how many times a user used the interface is just bad design.

~~~
tdumitrescu
Sorry about that, the example was developed as a standalone SPA with history
for the routing. But since we decided to embed it into the blog post itself,
the pushState routing doesn't make a lot of sense in that context.

~~~
justrobert
Ah I figured it'd be something like that.

I'm looking forward to a future where we use web components.

------
daxfohl
They remind me too much of WPF (.net ux tech) which I never cared for. Once I
moved to web dev with React I found that much simpler. Web Components seems
like a step backwards to me.

------
dmitriid
The lib "does so by providing an easy-to-use state management and rendering
layer built on Virtual DOM (the basis of the core rendering technology of
React). Through use of the Snabbdom Virtual DOM library and first-class
support for multiple templating formats".

How is this "making web components work" any different from making DOM work
via snabbdom or React?

------
ch3ster
A few months ago Mixpanel notified me that they had been accidentally
transmitting and storing passwords for some customers due to a UI issue. I
wonder if the re-architecting had something to do with that or if it was the
resolution.

------
victor106
Web Components are awesome. They will be the future. That said, I feel React
has good future just because of React Native. It’s amazing that you can
develop highly performant applications and target multiple platforms

~~~
RobertRoberts
Didn't Facebook stop using React Native in their own app (or part of it)
because it's performance was poor? Or the file size was gigantic, there was
something wrong...

------
philip1209
I'm surprised that the Mixpanel engineering blog is hosted on Wordpress with
the default theme. The default theme doesn't align with their designed brand,
and it makes me suspicious of whether they have taken steps to secure the
installation. For this low-effort of a blog, I would have expected them to use
Medium.

------
ausjke
while web components are interesting, how can you do native apps on top of it
when needed? e.g. vue-native, react-native etc, or at least support by
something like Electron etc.

or is it strictly a web-browser-only thing?

~~~
ernsheong
It's a browser spec, so yeah browser-only. Electron is browser-based (Chrome),
so web-components can be used there.

Check out [https://github.com/Polymer/pwa-starter-
kit/wiki](https://github.com/Polymer/pwa-starter-kit/wiki) for concrete
examples using LitElement ([https://github.com/Polymer/lit-
element](https://github.com/Polymer/lit-element))

------
la_fayette
i use stenciljs web component compiler. it is not a framework... it is great
as it lets you do things without having to worry about browser support.

------
dsschnau
web components are never happening

~~~
lintroller
That seems like a rather bold statement without much reasoning behind it. What
in particular makes you think that web components are "never happening"?

~~~
ropeadopepope
This looks less than promising: [https://caniuse.com/#feat=custom-
elements](https://caniuse.com/#feat=custom-elements)

~~~
tdumitrescu
That's the deprecated v0 spec, fyi.

~~~
ropeadopepope
[https://caniuse.com/#feat=custom-
elementsv1](https://caniuse.com/#feat=custom-elementsv1) doesn't look much
better.

~~~
Klathmon
Out of the 4 major browsers, 2 major browser vendors have support for the base
stuff, 1 has it behind a flag being tested ready to be turned on, and 1
doesn't have any support yet...

That's pretty far from "not happening"

