"Specifically, they’d like you to use Polymer. The problem is that the Web Component API is really unpleasant to use directly, especially compared to React. That’s really holding Polymer back in the framework marketplace. Other WC-based frameworks like Svelte, Skate, and Stencil abstract away from WCs, treating them as a compilation target."
That argument feels like a non-sequitur. Polymer's API is different from the Web Component API, so even if the Web Component API would be unpleasant to use directly, that is not a criticism of a different API (in this case the Polymer API). Polymer's API is "similar" to the native Web Component API though, but it's designed to be easier to use than the native API.
Polymer's API _is_ the Web Components API, with some helpers added for reacting to property changes, augmenting templating and a few others. Polymer is simply a base class for your elements that sits between HTMLElement and your component class.
But I don't really get the "Web Components APIs are unpleasant" line of criticism. The WC APIs are just the element constructor, connectedCallback, disconnectedCallback, attributeChangedCallback and what methods and properties you define on your component. These lifecycle methods are nearly identical to what you get in React and just about every other framework. If those don't have unpleasant APIs, Web Components don't.
Author here. It's not just me saying that Web Components are unpleasant. In the article, I linked to Sam Saccone of Google saying that the WC developer experience is significantly worse than React's developer experience.
"This of course is coming from someone who has used web components every work day for the last 2 years. Hard to ignore the DX gap that exists."
To which Alex Russell, also of Google and one of the architects of the WC API, replies, "Who's ignoring it?"
There are certainly some developers who compare and contrast Polymer and React and prefer Polymer, but it's fair to say that the vast majority of developers who have made this comparison have preferred React's developer experience. Even Polymer's advocates seem to be holding their nose and using it because they appreciate the long-term promise of Web Components interop.
Why? It's hard to say exactly, but I think it has to do with React's guarantees that the UI will be a pure function of state. Lots of nifty React features emerge from that. Polymer components make no such guarantees.
I'm actually pretty enthusiastic about lit-HTML as a way to close the gap. We'll see how it goes.
“To do this automatically” is followed by dosens of lines of tedious bolierplate. And that’s for a single most common use case of adding a property, and an attribute that are synced. It’s then followed by yet more boilerplate for adding a custom event.
To achieve pretty basic mutations on small components, children references and data manipulation there’s a lot of heavy lifting that really compromises the developer experience.
And it’s a big deal, since developer experience is one of the reasons why React or Vue are widely used in production.
Also, web components being included in a magical global store difficults declarative and deterministic views or any other concept which hangs on a visual map of dependencies like code splitting.
UNFORTUNATELY THE DEVELOPER EXPERIENCE OF BUILDING AN APPLICATION WITH WEB COMPONENTS TODAY IS QUITE PAINFUL
SAM SACCONE
I replied in general below, but I'll take some extra time to respond to the complaint about getters and setters.
Any JavaScript class that wants to define observable properties has to define a getter/setter pair.
Manually, this usually looks like this:
class C {
get foo() { return this._foo; }
set (foo(v) { this._foo = v; this._somethingChanged(); }
}
From the part of the article you reference, you're complaining that Web Components don't "solve" observable properties. This is because in JavaScript there are already ways to do this with with getters, setters, Object.defineProperty, and while that does involve some amount of "boilerplate" there are helpers for both Web Components and plain classes that will create these properties for you.
I really don't see why it's a valid criticism of Web Components that they don't magically solve this problem when it's just the way JavaScript works. Of course frameworks like Angular solve this problem by generating accessors for you - but so does every major Web Components library. They all include some way of letting an author declare observable properties and syncing them with attributes. Given that the end result in DX is exactly the same as with other frameworks, why the ding on Web Components? Why are Web Components held to a higher standard and expected to "fix" JavaScript?
To show how absolutely easy this is, and how off-base the DX complain is, here's how easy a Polymer 2 + TypeScript element is (TypeScript just to use decorators, which will be standards JS someday...)
That will create an observable property, fire a "foo-changed" event and set the "foo" attribute when it changes, and listen for the "foo" attribute and deserialize it to the foo property when the attribute is set.
Even without decorators, this is pretty damn easy to do, and the first thing any Polymer developer learns:
Other Web Components libraries like Skate and Stencil include their own way of declaring properties, just like other frameworks like Angular and Ember do.
The second article is also comparing raw Web Components with no helpers to a framework that's full of helpers. You could just as easily saw JavaScript has a broken DX if you tried to do React-style components without React. The higher expectation for Web Components here is kind of ridiculous, to be honest.
> I really don't see why it's a valid criticism of Web Components that they don't magically solve this problem when it's just the way JavaScript works.
IMO, React feels better and more productive in part because it doesn't have/need observables. It's the difference between a UI in "retained mode" and "immediate mode."
> Javascript
> you complain about objects
> don't magically solve
> raw WCs vs helpers
etc. etc. etc.
And then you wonder why I'm so set against WebComponents. Because you (and Rob Dodson and other WebComponent proponents) are entirely blind to how bad WebComponent APIs are. I dunno, maybe your goal isn't to "sell" WebComponents, but to sell Polymer.
WebComponent API is bad not because "we complain about how Javascript objects are". We complain because WebComponents API is horrendously bad, and that was a deliberate design choice.
Current line of defence is "oh, it's just low level API" or "oh, it's just how Javascript is", both of which are at best patently false.
Here's code to create one single property with one single synced attribute. One. single. property/attribute pair. One.
set transitionDuration(value) {
this.setAttribute('transition-duration', value);
}
get transitionDuration() {
return this.getAttribute('transition-duration');
}
static get observedAttributes() {
return ['transition-duration'];
}
attributeChangedCallback(name, oldVal, newVal) {
if (name === 'transition-duration') {
// do something
}
}
There is no reality where this is good API design. There is no reality where "this is how objects work in Javascript" is an excuse.
This is objectivly bad API design. Bad developer experience. However, you and all other webcomponent proponents completely ignore this fact, and dismiss any and all complaints out of hand.
Of course you do. You've got Polymer to promote [1]. If WebComponents had better APIs, there would be no need for Polymer, would there. Because here's how Polymer solves the problem, despite this being "oh, that's how Javascript works".
Oh. My. God. This is doable without any excuses about how Javascript works? Really? Who would've thunk it?
[1] Hell, even in your "rebuttal" of criticism towards WebComponents here's what you write:
> To show how absolutely easy this is, and how off-base the DX complain is, here's how easy a Polymer 2 + TypeScript element is
Were we talking about the bad DX of Polymer? No. You are totally entirely absolutely blind to the fact though. Because in your mind WebComponents === Polymer. And, sadly, for all intents and purposes it's true.
"maybe your goal isn't to "sell" WebComponents, but to sell Polymer."
The goal of Web Components are to sell a interop layer that is supported by many (or even all) frameworks. It's not supposed to be a framework that has the best developing experience.
The Polymer API is better than the Web Components API. The Polymer API is more high level than the Web Components API. This is not by mistake, it's by design. The higher level the Web Components API is, the more difficult it is to use by a large number of wildly different frameworks.
"We complain because WebComponents API is horrendously bad, and that was a deliberate design choice."
I don't think it matters much to be honest, because developers should use frameworks, just like they are using frameworks at the moment.
"Here's code to create one single property with one single synced attribute. One. single. property/attribute pair. One."
You need a "synced attribute" only for some frameworks, not all. Also, your example is misleading, because the two last methods are only needed to be defined once, so if you want 2 synced properties, the total number of methods is 6, not 8.
"Bad developer experience."
Use a framework.
"If WebComponents had better APIs, there would be no need for Polymer, would there."
The risk is too high to use the Polymer API for the Web Componenets API. In addition, the more complex the API is, the more likely it is for the browsers not to implement the API. It's better to have a simple native API and provide different frameworks for a good user experience.
"Because in your mind WebComponents === Polymer."
Or maybe he thinks that frameworks should be used, as intended.
> The goal of Web Components are to sell a interop layer that is supported by many
> Or maybe he thinks that frameworks should be used, as intended.
Translation: instead of providing a good DX we're going to sell Polymer
> The Polymer API is more high level than the Web Components API. This is not by mistake, it's by design.
Indeed. By crappy design with horrible developer experience
> The higher level the Web Components API is, the more difficult it is to use by a large number of wildly different frameworks.
Hmm... How about "let's reduce the need for and dependency on multiple frameworks"? When will that ever be a goal?
> You need a "synced attribute" only for some frameworks, not all.
Surprise, Polymer's API provides a possibility to define that.
> Also, your example is misleading, because the two last methods are only needed to be defined once, so if you want 2 synced properties, the total number of methods is 6, not 8.
Oh. Right. 6, not 8. I wonder if I ever complained about the number of methods required? Nope, what I complained about is the amount of tedious boilerplate you need to write to implement the most basic and common of things.
If I need 1 more synced property/attribute pair, I will need:
- 1 extra setter
- 1 extra getter
- 1 extra item in the attributes list
- 1 extra if clause in the callback.
>> "Bad developer experience."
> Use a framework.
How about: platform provides a well-designed API that doesn't require a framework for the most basic and common functionality?
As an example:
- DOM APIs are horrible, and quickly devolve into tedious error-prone boilerplate
- jQuery API is amazing
- Does this mean that DOM APIs suddenly become developer friendly? Does this mean they are beyond any criticism?
"Hmm... How about "let's reduce the need for and dependency on multiple frameworks"? When will that ever be a goal?"
That's not a realistic goal, because there's no common agreement on the framework API. If there were, every framework would have the same API already.
"Surprise, Polymer's API provides a possibility to define that."
Your point being?
"Oh. Right. 6, not 8. I wonder if I ever complained about the number of methods required? Nope, what I complained about is the amount of tedious boilerplate you need to write to implement the most basic and common of things."
You're not intellectually honest, so I will stop this discussion.
The moment I call you out twisting my words, you call me intellectually dishonest. Suit yourself. This entire discussion shows the actual intellectual dishonesty of people who defend WebComponents.
> Your point being
You, and others are completely entirely blind to the fact that:
- WebComponent API is horrible DX
- WebComponent API can be made better within the platform, without the need to rely on third-party frameworks.
However, if the goal is not to push WebComponents forward, but to sell Polymer to as many devs as possible, it’s not surprising.
Web components are a set of web platform APIs that allow you to create new custom, reusable, encapsulated HTML tags to use in web pages and web apps. Custom components and widgets build on the Web Component standards, will work across modern browsers, and can be used with any JavaScript library or framework that works with HTML.
--- end quote ---
They don't allow any of that, do they? Because, as you so eloquently put, "use a framework". As I'm already using a framework (there are dozens of them out there), what is the selling point of WCs exactly?
My point differs from the opinion of someone else (not sure who you quoted).
" As I'm already using a framework (there are dozens of them out there), what is the selling point of WCs exactly?"
To provide interop between frameworks, so that we don't need to write the same components 10 times for each framework. We can just implmenet it once, and use a native API to use it from any framework.
"Oh, right. "Use Polymer", how can I ever forget."
There are and will be other frameworks which support the Web Components API.
You're disingenuous, so this will be my only response:
In your first example you have code for using raw Web Components, and presumably it's "bad" user experience compared to a framework that generates this code for you. It's not a valid comparison.
Either compare a Web Components library, like Polymer, Skate, or Stencil, that generates this code for you against a framework, or compare raw Web Components against raw JavaScript without a framework. You'll find that making state observable and syncing it across attributes will require even more code than Web Components.
In your second example you're showing a high-level declarative API, that has opinions about property name to attribute name to event name mapping, includes a format for per-property meta-data, options for triggering observer methods, whether or not to sync attributes, and how to deserialize from attributes.
There's no way that level of API and opinion are appropriate for the underlying platform, which has to be responsible first for the capabilities of the system, the low-level hooks, and how the components interoperate with the host and other components. Higher-level libraries can automatically implement the hooks with opinions.
Even in raw JavaScript, it takes boilerplate to make an observable property, and libraries can generate that for you. Why are you holding Web Components to a higher standard than JavaScript?
> Even in raw JavaScript, it takes boilerplate to make an observable property, and libraries can generate that for you. Why are you holding Web Components to a higher standard than JavaScript?
Because WebComponents are not raw Javascript. It’s an API.
There’s nothing stopping you from providing an API with good DX. Except one fact: you are entirely blind to the fact that WebComponent API is bad.
It’s also funny how you call me disingenuous when your line of defence is “DX criticism is invalid because see how easy it is with Polymer”.
If for every single point your answer is “use polymer/helper”, it only means one thing: the API is bad, and you don’t care.
I think ya'll are kinda talking past each other, and you may agree more than it appears.
The DX for raw web components, without any library, is awkward and verbose to handle observing changes well. I think the point of departure is that we (Polymer) see this as a problem that's true of all JS, not just Web Components, and it would be better to solve it for all JS through a mechanism like decorators, which is going through the standards process now and we're big supporters of it.
So, yes, creating getters and setters and observing changes is awkward. Yes we should fix it for web components, but the best place to do that is to fix it is actually at the javascript level, which is in process! :D
This is a criticism of Objects, not Web Components, and most framework/component libraries out there assists in creating properties that can be observed, from Ember to Angular to Polymer. That Web Components don't solve a problem that applies to the whole of JavaScript, but Web Components libraries do, does not seem like a very serious criticism to me.
> and an attribute
Adding an attribute name to `observedAttributes` and listening for the change in `attributeChanged` callback is not very onerous, and similar to frameworks that have attributes callbacks. How else do you propose listening to an attribute? Regardless, and again, libraries help do this small bit for you, and combine it with a property for a single, declarative property/attribute definition.
> and a custom event
"Defining" a custom event is as simple as firing it, and since they're standard DOM events, if you find the CustomEvent/dispatchEvent API too difficult to use, you could write or use a small helper. I'm not totally sure what it would do, since those APIs are so simple. And yet again, libraries like Polymer include firing events when properties change as a declarative option, to make it even simpler.
I know you have a major axe to grind with Web Components on Twitter. I'm not sure what set you off about them, and I know I won't change your mind. I only responded for other readers here.
What's the download tariff on Polymer vs React (I'll admit, I haven't checked library sizes for polymer since 2014) Do they allow for this 150k initial bundle?
It's pretty small. I'm working on an internal application using Polymer 3.0-rc1 currently, with some basic Paper elements (button, input, icon, spinner, tabs, app-route). The whole app bundle (made with rollup + babel-minify) is ~90k gzipped, ~200k uncompressed.
That argument feels like a non-sequitur. Polymer's API is different from the Web Component API, so even if the Web Component API would be unpleasant to use directly, that is not a criticism of a different API (in this case the Polymer API). Polymer's API is "similar" to the native Web Component API though, but it's designed to be easier to use than the native API.