545

What are the main benefits of Facebook's React over the upcoming Web Components spec and vice versa (or perhaps a more apples-to-apples comparison would be to Google's Polymer library)?

According to this JSConf EU talk and the React homepage, the main benefits of React are:

  • Decoupling and increased cohesion using a component model
  • Abstraction, Composition and Expressivity
  • Virtual DOM & Synthetic events (which basically means they completely re-implemented the DOM and its event system)
    • Enables modern HTML5 event stuff on IE 8
    • Server-side rendering
    • Testability
    • Bindings to SVG, VML, and <canvas>

Almost everything mentioned is being integrated into browsers natively through Web Components except this virtual DOM concept (obviously). I can see how the virtual DOM and synthetic events can be beneficial today to support old browsers, but isn't throwing away a huge chunk of native browser code kind of like shooting yourself in the foot in the long term? As far as modern browsers are concerned, isn't that a lot of unnecessary overhead/reinventing of the wheel?

Here are some things I think React is missing that Web Components will take care of for you. Correct me if I'm wrong.

  • Native browser support (read "guaranteed to be faster")
  • Write script in a scripting language, write styles in a styling language, write markup in a markup language.
  • Style encapsulation using Shadow DOM
    • React instead has this, which requires writing CSS in JavaScript. Not pretty.
  • Two-way binding
CletusW
  • 5,453
  • 3
  • 14
  • 6
  • 2
    Style encapsulation in react is messy. I certainly prefer web components when it comes to that use case. I want to know what the performance boost of react is over web components assuming there is one? I keep hearing people say performance but what do the numbers say and is it worth it? Also, i think multiple representations of the dom elements and the things they contain can get messy...i tend to think of react as version control for the dom. – AdonisSMU Feb 04 '14 at 13:28
  • I'm inclined to believe that Web Components will have a significant advantage as far as performance in that it will be a native feature of the browser (which means it can be written in C++ or whatever the browser uses). – CletusW Feb 04 '14 at 19:04
  • @AdonisSMU i have been trying to solve the styling issue with react and this is what i came up with, it blends well with the everything is a component mentality - http://github.com/icodeforlove/react-rcs (its a WIP) – Chad Scira Jul 15 '14 at 23:08
  • 15
    Wrt. two way binding. This feature is problematic at scale. In trivial cases it works well, but in real-world cases you typically find that to keep the code manageable you require a viewmodel to bind against, instead of binding against the actual model, which then makes the two-way binding much less useful than it initially seemed. I think it may be an advantage of React that it doesn't provide two-way binding because it forces proper data flow architecture. – Joeri Sebrechts Dec 10 '14 at 09:15
  • @JoeriSebrechts While you are absolutely correct about 2-way binding in large applications, it is *sometimes* an advantage when working with a component/control model in mind. Also, 2-way binding is an optional feature of Polymer/WebComponents. It must be declared in some way for it to be applied to a attribute/property. – Fuzzical Logic Jan 24 '15 at 08:27
  • 9
    I've looked at React, Angular and Knockout. I find Knockout the 'cleanest' in terms of separation of ui templating, data and binding. I wanted to like react, but trying to create a simple Combobox, i realize i was writing way more code and mixing rendering logic with html templating..much more so than i would by using something like html/jina2. Seems to me these libraries/apis are moving us backwards, not forward. The best thing about React is the virtual dom manipulation, but i can see that coming to other established frameworks sooner than later. – mike01010 Mar 20 '15 at 04:57
  • 1
    I'm a huge exponent of webcomponents and what it brings to the web. I've been working recently on introducing webcomponents to React: https://github.com/Wildhoney/Maple.js – Wildhoney May 28 '15 at 19:22
  • 47
    I'm very surprised (and also pleased!) that this question didn't get shut down as "primarily opinion-based". – iconoclast Jul 06 '15 at 16:08
  • 4
    It is not possible to write "script in a scripting language" and "markup in a markup language" if you are doing templating of any sort. Angular, polymer, etc. use a template DSL embedded in HTML. React uses a template DSL embedded in JS (JSX). The problem with embedding a DSL in HTML is how to establish scope for getting values from the JS. This leads to Angular's complex $scope system. In JSX, on the other hand, the scope of variables in templates is just JS scope -- I find it much less confusing. – Andy Aug 27 '15 at 17:24
  • Also Polymer is just one tool for building web components. I'm sure someday you'll be able to mount React components or Angular stuff in web components if you want. – Andy Aug 27 '15 at 17:29
  • Native browser support definitely should NOT read "guaranteed to be faster" - in a lot of cases it is slower because the spec is implemented properly and thoroughly - lots of edge cases being taken into consideration that pollyfills do not bother with - allowing them to be faster than the native implementation – iwayneo Sep 01 '15 at 15:22
  • 3
    At the moment React components (unless badly written) would be faster than the same in any DOM-bound framework. The v-dom and diff-ing magic is the USP of react. My point is - Why would the browers not build a diff-ing like that in their native featureset. What stops them, and if nothing (stops them) then the lead of React is probably going to be short-lived. – fasttrainofthoughts Nov 02 '15 at 06:58
  • 3
    Seems like this question has so far skipped the glance of the vigilantes who routinely close questions of such nature. I hope they continue to stay away and mind their own business – Abbas Gadhia Mar 08 '16 at 12:52
  • The biggest React con has nothing to do with technology. May 2019 the W3C and WHATWG agreed the WHATWG is in the lead on developing the HTML and DOM standards. WHATWG membership is by invitation only... and to date **the WHATWG core members** (Apple, Mozilla, Google & Microsoft) haven't invited Facebook yet... Guess who **are** developing "Web Components" – Danny '365CSI' Engelman Apr 05 '21 at 14:06

6 Answers6

691

Update: this answer seems to be pretty popular so I took some time to clean it up a little bit, add some new info and clarify few things that I thought were not clear enough. Please comment if you think anything else needs clarification or updates.

Most of your concerns are really a matter of opinion and personal preference but I'll try to answer as objectively as I can:

Native vs. Compiled

Write JavaScript in vanilla JavaScript, write CSS in CSS, write HTML in HTML.

Back in the day there were hot debates whether one should write native Assembly by hand or use a higher level language like C to make the compiler generate Assembly code for you. Even before that people refused to trust assemblers and preferred to write native machine code by hand (and I'm not joking).

Meanwhile, today there are a lot of people who write HTML in Haml or Jade, CSS in Sass or Less and JavaScript in CoffeeScript or TypeScript. It's there. It works. Some people prefer it, some don't.

The point is that there is nothing fundamentally wrong in not writing JavaScript in vanilla JavaScript, CSS in CSS and HTML in HTML. It's really a matter of preference.

Internal vs. External DSLs

 Style encapsulation using Shadow DOM  React instead has this, which requires writing CSS in JavaScript. Not pretty.

Pretty or not, it is certainly expressive. JavaScript is a very powerful language, much more powerful than CSS (even including any of CSS preprocessors). It kind of depends on whether you prefer internal or external DSLs for those sorts of things. Again, a matter of preference.

(Note: I was talking about the inline styles in React that was referenced in the original question.)

Types of DSLs - explanation

Update: Reading my answer some time after writing it I think that I need to explain what I mean here. DSL is a domain-specific language and it can be either internal (using syntax of the host language like JavaScript - like for example React without JSX, or like the inline styles in React mentioned above) or it can be external (using a different syntax than the host language - like in this example would be inlining CSS (an external DSL) inside JavaScript).

It can be confusing because some literature uses different terms than "internal" and "external" to describe those kinds of DSLs. Sometimes "embedded" is used instead of "internal" but the word "embedded" can mean different things - for example Lua is described as "Lua: an extensible embedded language" where embedded has nothing to do with embedded (internal) DSL (in which sense it is quite the opposite - an external DSL) but it means that it is embedded in the same sense that, say, SQLite is an embedded database. There is even eLua where "e" stands for "embedded" in a third sense - that it is meant for embedded systems! That's why I don't like using the term "embedded DSL" because things like eLua can be "DSLs" that are "embedded" in two different senses while not being an "embedded DSL" at all!

To make things worse some projects introduce even more confusion to the mix. Eg. Flatiron templates are described as "DSL-free" while in fact it is just a perfect example of an internal DSL with syntax like: map.where('href').is('/').insert('newurl');

That having been said, when I wrote "JavaScript is a very powerful language, much more powerful than CSS (even including any of CSS preprocessors). It kind of depends on whether you prefer internal or external DSLs for those sorts of things. Again, a matter of preference." I was talking about those two scenarios:

One:

/** @jsx React.DOM */
var colored = {
  color: myColor
};
React.renderComponent(<div style={colored}>Hello World!</div>, mountNode);

Two:

// SASS:
.colored {
  color: $my-color;
}
// HTML:
<div class="colored">Hello World!</div>

The first example uses what was described in the question as: "writing CSS in JavaScript. Not pretty." The second example uses Sass. While I agree that using JavaScript to write CSS may not be pretty (for some definitions of "pretty") but there is one advantage of doing it.

I can have variables and functions in Sass but are they lexically scoped or dynamically scoped? Are they statically or dynamically typed? Strongly or weakly? What about the numeric types? Type coersion? Which values are truthy and which are falsy? Can I have higher-order functions? Recursion? Tail calls? Lexical closures? Are they evaluated in normal order or applicative order? Is there lazy or eager evaluation? Are arguments to functions passed by value or by reference? Are they mutable? Immutable? Persistent? What about objects? Classes? Prototypes? Inheritance?

Those are not trivial questions and yet I have to know answers to them if I want to understand Sass or Less code. I already know those answers for JavaScript so it means that I already understand every internal DSL (like the inline styles in React) on those very levels so if I use React then I have to know only one set of answers to those (and many similar) questions, while when I use for eg. Sass and Handlebars then I have to know three sets of those answers and understand their implications.

It's not to say that one way or the other is always better but every time you introduce another language to the mix then you pay some price that may not be as obvious at a first glance, and this price is complexity.

I hope I clarified what I originally meant a little bit.

Data binding

Two-way binding

This is a really interesting subject and in fact also a matter of preference. Two-way is not always better than one-way. It's a question of how do you want to model mutable state in your application. I always viewed two-way bindings as an idea somewhat contrary to the principles of functional programming but functional programming is not the only paradigm that works, some people prefer this kind of behavior and both approaches seem to work pretty well in practice. If you're interested in the details of the design decisions related to the modeling of the state in React then watch the talk by Pete Hunt (linked to in the question) and the talk by Tom Occhino and Jordan Walke who explain it very well in my opinion.

Update: See also another talk by Pete Hunt: Be predictable, not correct: functional DOM programming.

Update 2: It's worth noting that many developers are arguing against bidirectional data flow, or two-way binding, some even call it an anti-pattern. Take for example the Flux application architecture that explicitly avoids the MVC model (that proved to be hard to scale for large Facebook and Instagram applications) in favor of a strictly unidirectional data flow (see the Hacker Way: Rethinking Web App Development at Facebook talk by Tom Occhino, Jing Chen and Pete Hunt for a good introduction). Also, a lot of critique against AngularJS (the most popular Web framework that is loosely based on the MVC model, known for two-way data binding) includes arguments against that bidirectional data flow, see:

Update 3: Another interesting article that nicely explains some of the issues disscussed above is Deconstructing ReactJS's Flux - Not using MVC with ReactJS by Mikael Brassman, author of RefluxJS (a simple library for unidirectional data flow application architecture inspired by Flux).

Update 4: Ember.js is currently going away from the two-way data binding and in future versions it will be one-way by default. See: The Future of Ember talk by Stefan Penner from the Embergarten Symposium in Toronto on November 15th, 2014.

Update 5: See also: The Road to Ember 2.0 RFC - interesting discussion in the pull request by Tom Dale:

"When we designed the original templating layer, we figured that making all data bindings two-way wasn't very harmful: if you don't set a two-way binding, it's a de facto one-way binding!

We have since realized (with some help from our friends at React), that components want to be able to hand out data to their children without having to be on guard for wayward mutations.

Additionally, communication between components is often most naturally expressed as events or callbacks. This is possible in Ember, but the dominance of two-way data bindings often leads people down a path of using two-way bindings as a communication channel. Experienced Ember developers don't (usually) make this mistake, but it's an easy one to make." [emphasis added]

Native vs. VM

Native browser support (read "guaranteed to be faster")

Now finally something that is not a matter of opinion.

Actually here it is exactly the other way around. Of course "native" code can be written in C++ but what do you think the JavaScript engines are written in?

As a matter of fact the JavaScript engines are truly amazing in the optimizations that they use today - and not only V8 any more, also SpiderMonkey and even Chakra shines these days. And keep in mind that with JIT compilers the code is not only as native as it can possibly be but there are also run time optimization opportunities that are simply impossible to do in any statically compiled code.

When people think that JavaScript is slow, they usually mean JavaScript that accesses the DOM. The DOM is slow. It is native, written in C++ and yet it is slow as hell because of the complexity that it has to implement.

Open your console and write:

console.dir(document.createElement('div'));

and see how many properties an empty div element that is not even attached to the DOM has to implement. These are only the first level properties that are "own properties" ie. not inherited from the prototype chain:

align, onwaiting, onvolumechange, ontimeupdate, onsuspend, onsubmit, onstalled, onshow, onselect, onseeking, onseeked, onscroll, onresize, onreset, onratechange, onprogress, onplaying, onplay, onpause, onmousewheel, onmouseup, onmouseover, onmouseout, onmousemove, onmouseleave, onmouseenter, onmousedown, onloadstart, onloadedmetadata, onloadeddata, onload, onkeyup, onkeypress, onkeydown, oninvalid, oninput, onfocus, onerror, onended, onemptied, ondurationchange, ondrop, ondragstart, ondragover, ondragleave, ondragenter, ondragend, ondrag, ondblclick, oncuechange, oncontextmenu, onclose, onclick, onchange, oncanplaythrough, oncanplay, oncancel, onblur, onabort, spellcheck, isContentEditable, contentEditable, outerText, innerText, accessKey, hidden, webkitdropzone, draggable, tabIndex, dir, translate, lang, title, childElementCount, lastElementChild, firstElementChild, children, nextElementSibling, previousElementSibling, onwheel, onwebkitfullscreenerror, onwebkitfullscreenchange, onselectstart, onsearch, onpaste, oncut, oncopy, onbeforepaste, onbeforecut, onbeforecopy, webkitShadowRoot, dataset, classList, className, outerHTML, innerHTML, scrollHeight, scrollWidth, scrollTop, scrollLeft, clientHeight, clientWidth, clientTop, clientLeft, offsetParent, offsetHeight, offsetWidth, offsetTop, offsetLeft, localName, prefix, namespaceURI, id, style, attributes, tagName, parentElement, textContent, baseURI, ownerDocument, nextSibling, previousSibling, lastChild, firstChild, childNodes, parentNode, nodeType, nodeValue, nodeName

Many of them are actually nested objects - to see second level (own) properties of an empty native div in your browser, see this fiddle.

I mean seriously, onvolumechange property on every single div node? Is it a mistake? Nope, it's just a legacy DOM Level 0 traditional event model version of one of the event handlers "that must be supported by all HTML elements, as both content attributes and IDL attributes" [emphasis added] in Section 6.1.6.2 of the HTML spec by W3C - no way around it.

Meanwhile, these are the first level properties of a fake-DOM div in React:

props, _owner, _lifeCycleState, _pendingProps, _pendingCallbacks, _pendingOwner

Quite a difference, isn't it? In fact this is the entire object serialized to JSON (LIVE DEMO), because hey you actually can serialize it to JSON as it doesn't contain any circular references - something unthinkable in the world of native DOM (where it would just throw an exception):

{
  "props": {},
  "_owner": null,
  "_lifeCycleState": "UNMOUNTED",
  "_pendingProps": null,
  "_pendingCallbacks": null,
  "_pendingOwner": null
}

This is pretty much the main reason why React can be faster than the native browser DOM - because it doesn't have to implement this mess.

See this presentation by Steven Luscher to see what is faster: native DOM written in C++ or a fake DOM written entirely in JavaScript. It's a very fair and entertaining presentation.

Update: Ember.js in future versions will use a virtual DOM heavily inspired by React to improve perfomance. See: The Future of Ember talk by Stefan Penner from the Embergarten Symposium in Toronto on November 15th, 2014.

To sum it up: features from Web Components like templates, data binding or custom elements will have a lot of advantages over React but until the document object model itself gets significantly simplified then performance will not be one of them.

Update

Two months after I posted this answers there was some news that is relevant here. As I have just written on Twitter, the lastest version of the Atom text editor written by GitHub in JavaScript uses Facebook's React to get better performance even though according to Wikipedia "Atom is based on Chromium and written in C++" so it has full control of the native C++ DOM implementation (see The Nucleus of Atom) and is guaranteed to have support for Web Components since it ships with its own web browser. It is just a very recent example of a real world project that could've used any other kind of optimization typically unavailable to Web applications and yet it has chosen to use React which is itself written in JavaScript, to achieve best performance, even though Atom was not built with React to begin with, so doing it was not a trivial change.

Update 2

There is an interesting comparison by Todd Parker using WebPagetest to compare performance of TodoMVC examples written in Angular, Backbone, Ember, Polymer, CanJS, YUI, Knockout, React and Shoestring. This is the most objective comparison that I've seen so far. What is significant here is that all of the respective examples were written by experts in all of those frameworks, they are all available on GitHub and can be improved by anyone who thinks that some of the code could be optimized to run faster.

Update 3

Ember.js in future versions will include a number of React's features that are discussed here (including a virtual DOM and unidirectional data binding, to name just a few) which means that the ideas that originated in React are already migrating into other frameworks. See: The Road to Ember 2.0 RFC - interesting discussion in the pull request by Tom Dale (Start Date: 2014-12-03): "In Ember 2.0, we will be adopting a "virtual DOM" and data flow model that embraces the best ideas from React and simplifies communication between components."

As well, Angular.js 2.0 is implementing a lot of the concepts discussed here.

Update 4

I have to elaborate on few issues to answer this comment by Igwe Kalu:

"it is not sensible to compare React (JSX or the compilation output) to plain JavaScript, when React ultimately reduces to plain JavaScript. [...] Whatever strategy React uses for DOM insertion can be applied without using React. That said, it doesn't add any special benefits when considering the feature in question other than the convenience." (full comment here)

In case it wasn't clear enough, in part of my answer I am comparing the performance of operating directly on the native DOM (implemented as host objects in the browser) vs. React's fake/virtual DOM (implemented in JavaScript). The point I was trying to make is that the virtual DOM implemented in JavaScript can outperform the real DOM implemented in C++ and not that React can outperform JavaScript (which obviously wouldn't make much sense since it is written in JavaScript). My point was that "native" C++ code is not always guaranteed to be faster than "not-native" JavaScript. Using React to illustrate that point was just an example.

But this comment touched an interesting issue. In a sense it is true that you don't need any framework (React, Angular or jQuery) for any reason whatsoever (like performance, portability, features) because you can always recreate what the framework does for you and reinvent the wheel - if you can justify the cost, that is.

But - as Dave Smith nicely put it in How to miss the point when comparing web framework performance: "When comparing two web frameworks, the question is not can my app be fast with framework X. The question is will my app be fast with framework X."

In my 2011 answer to: What are some empirical technical reasons not to use jQuery I explain a similar issue, that it is not impossible to write portable DOM-manipulation code without a library like jQuery, but that people rarely do so.

When using programming languages, libraries or frameworks, people tend to use the most convenient or idiomatic ways of doing things, not the perfect but inconvenient ones. The true value of good frameworks is making easy what would otherwise be hard to do - and the secret is making the right things convenient. The result is still having exactly the same power at your disposal as the simplest form of lambda calculus or the most primitive Turing machine, but the relative expressiveness of certain concepts means that those very concepts tend to get expressed more easily or at all, and that the right solutions are not just possible but actually implemented widely.

Update 5

React + Performance = ? article by Paul Lewis from July 2015 shows an example where React is slower than vanilla JavaScript written by hand for an infinite list of Flickr pictures, which is especially significant on mobile. This example shows that everyone should always test performance for specific use case and specific target platforms and devices.

Thanks to Kevin Lozandier for bringing it to my attention.

rsp
  • 7,858
  • 1
  • 17
  • 10
  • 81
    that's what I call a comprehensive answer, thanks! – 0xDonut May 24 '14 at 00:25
  • 1
    With regards to your first point, I edited the question to reflect my intention: "Write script in a scripting language, write styles in a styling language, write markup in a markup language." Obviously it's still valid to prefer writing styles in JavaScript, I just love that Web Components gets us back to a place where we even have the *option* to do it in a styling language and still get all the other benefits. All of your other points are wonderful, though! I'm just waiting to hear an argument for the other side before I accept an answer. – CletusW Jun 04 '14 at 20:06
  • 2
    I'm missing why you think styling is baked into react. I thought it just output HTML. The CSS is still entirely separate. As for the HTML it outputs, as they've stated many times, you don't have to use JSX. You're free to create and use HTML snippets anyway you like including reading them from some file written by a designer. – gman Jun 18 '14 at 11:52
  • Amazing answer, so much documentation for your ideas! great. – Rowe Morehouse Jun 27 '14 at 18:42
  • @gman I was talking about inline styles in React that are written in JS - see: http://facebook.github.io/react/tips/inline-styles.html – rsp Jul 13 '14 at 01:43
  • @rsp i have been trying to solve the styling issue with react and this is what i came up with, it blends well with the everything is a component mentality - https://github.com/icodeforlove/react-rcs (its a WIP) – Chad Scira Jul 14 '14 at 23:32
  • 14
    Looks like Atom is moving away from React. See https://github.com/atom/atom/issues/3677 . – Juho Vepsäläinen Nov 16 '14 at 17:50
  • 1
    @bebraw No, it's not: "The DOM update mechanisms remain the same — it's even still using React." https://github.com/atom/atom/issues/3677#issuecomment-62783491 – ash Nov 19 '14 at 23:53
  • 6
    @ash: If you read further down the thread, they talk about how they would like to eventually move completely away from React and other frameworks, and just roll their own using custom elements and the shadow DOM. – musicfreak Dec 07 '14 at 06:48
  • No benchmarks to support the claims that it is so fast. Neither here, nor on the React website. [This benchmark](http://www.petehunt.net/react/tastejs/benchmark.html) shows that it is slower than vanilla js. Another confirmation that it is slow in [a comment by one of github Atom developers](http://www.petehunt.net/react/tastejs/benchmark.html). – Czarek Tomczak Dec 10 '14 at 20:02
  • 2
    @CzarekTomczak no JS library will ever be "faster that vanilla JS" because they are all **written in** vanilla JS, therefore in principle every optimization that React does you can do yourself, but in practice - well, good luck! See [this presentation by Steven Luscher](http://youtu.be/1OeXsL5mr4g) for a demonstration of what use case is React most optimized for. Basically it avoids write-read-write to the DOM which is otherwise very hard to avoid manually for certain tasks. – rsp Dec 10 '14 at 20:21
  • @CzarekTomczak Also using the fake DOM and diffing it with the previous state means that there are less changes to the DOM. For a good objective comparison see [this test by Todd Parker](https://twitter.com/pocztarski/status/537078929916694528) that compares the performance of [TodoMVC](http://todomvc.com/) examples written in Angular, Backbone, Ember, Polymer, CanJS, YUI, Knockout, React and Shoestring. This is the most objective comparison that I've seen so far. – rsp Dec 10 '14 at 20:45
  • @bebraw, ash, musicfreak: The actual [reasons Atom decided to ditch React](https://github.com/atom/atom/issues/3677#issuecomment-64126787) are proofing API compatibility (React is still in 0.x) and package author freedom. Not performance. – pilau Feb 14 '15 at 07:48
  • 1
    I would add [PureScript](http://www.purescript.org), [Elm](http://elm-lang.org), [Haste](http://haste-lang.org), [Fay](https://github.com/faylang/fay/wiki), [GHCJS](http://ghcjs.org), [Scala.js](http://www.scala-js.org) and [ClojureScript](https://github.com/clojure/clojurescript) to the list of things people use to write JS. Also, there's a new kid on the block called FRP; I'd recommend looking up some of the (mainly Haskell based) FRP blog posts, frameworks and libraries — these shed very interesting light on the topic WRT e.g. data-binding, composability, modularity and declarative UIs. – Erik Kaplun May 05 '15 at 10:41
  • 1
    Here's a good intro: https://www.youtube.com/watch?v=gaG3tIb3Lbk — again, based on a Haskell FRP GUI framework, but the ideas, topics covered and fundamental problems and solutions highlighted apply universally to any modern, functional (which JS frameworks are, to a substantial extent) GUI framework. – Erik Kaplun May 05 '15 at 10:43
  • 3
    Just to clarify the wording above, on @ErikAllik 's list, FRP (Functional Reactive Programming) is not a new language but rather an approach that's gaining popularity. In fact, "Elm is based on the idea of Functional Reactive Programming" (from elm-lang.org), and as he mentioned, there are FRP frameworks for Haskell, etc. – Jon Coombs May 18 '15 at 20:44
  • 2
    The amount of videos recommended here would easily fill a day, but are there any in-depth articles for those who don't have the time? – Dmitri Zaitsev May 21 '15 at 05:26
  • 1
    Just wanted to give you kudos for a well written, well researched, comprehensive answer that identifies which parts are fact and which are opinion - a rarity on the internet these days. Good job (and extremely helpful)! – Isochronous Jun 18 '15 at 20:14
  • 5
    tl;read anyway - brilliant, detailed answer! – Mark K Cowan Sep 01 '15 at 15:19
  • 1
    @rsp, it is not sensible to compare React to plain JavaScript, when React ***ultimately*** compiles to plain JavaScript. If your implementation of a solution with React performs better than another implemented directly with JavaScript, it means you are not able to write efficient JavaScript. But it does not mean React performs better than plain JavaScript. – Igwe Kalu Sep 04 '15 at 11:27
  • @IgweKalu React doesn't compile to plain JavaScript - it **is** plain JavaScript. What I was comparing was native DOM (implemented as host objects in the browser) vs. [React's fake/virtual DOM](https://facebook.github.io/react/docs/glossary.html) (implemented in JavaScript). The point is that the virtual DOM implemented in JavaScript can outperform the real DOM implemented in C++ and not that React can outperform JavaScript, which - as you correctly point out - wouldn't make much sense since it is written in JavaScript. So I agree with you but maybe I wasn't clear enough in my answer. – rsp Sep 04 '15 at 11:51
  • @rsp, I'll first rephrase - ***it is not sensible to compare React (JSX or the compilation output) to plain JavaScript, when React ultimately reduces to plain JavaScript.*** Then coming back to your response - it still does not make sense. Whatever strategy React uses for DOM insertion can be applied without using React. That said, it doesn't add any special benefits when considering the feature in question other than the convenience. – Igwe Kalu Sep 04 '15 at 12:51
  • 1
    @IgweKalu True. It can be said about pretty much any framework in existence. I don't need any framework - I can always reinvent them. But the question is - is it worth it? I updated my answer to talk about the issues from your comments - see the section: Update 4. – rsp Sep 04 '15 at 16:02
  • Well said......{comment buffer} – GONeale Oct 05 '15 at 23:47
  • The only consern on that test is that he uses dated Ember, idk why todo mvc uses dated one, but it would be nice to see it after "big rewrite", after 1.13.*, when glimmer landed – Restuta Nov 20 '15 at 06:35
  • 3
    Atom is moving to web components. – Nikos Nov 27 '15 at 10:51
  • 3
    It didn't seem like it was covered in the post, but the real reason to prefer Web Components, long term, is interoperability. A React component can only work inside a React app. A Web Component can work in an Angular app, a React app, an Ember app, etc. Also, Web Components and these frameworks are not mutually exclusive. You can combine them (there are many Polymer + Angular apps out there) and when the web component standards are shipping everywhere this story will get even better. – robdodson Dec 10 '15 at 17:47
  • 1
    [Atom has removed React because of how much overhead it adds](https://github.com/atom/atom/pull/5624) – Izkata Mar 13 '16 at 04:18
  • 2
    Any conclusion would be helpful. – wener Apr 21 '16 at 09:17
  • 2
    Well this is the best explanation of the whole thing that I have seen so far and after reading I get the feeling that I should avoid all those UI labraries. I was going to start doing a Web Project (am I BE developer) and I did a fair bit of javascript programming a while ago, and after reading about all these libraries all I can see is that those web giants are trying to move you away from native stuff to their own libraries. Why would I swap a clear design (javascript, css and html) with that React syntax? Virtual DOM for performance?! LOL – MeTitus May 07 '16 at 20:08
  • This answer implies that MVC always includes 2-way data-binding. It does not. In fact, it does not require the use of the so-called "observer pattern" at all. MVC was invented by Trygve Reenskaug and its central concept is that user interfaces and the application code should be written in such a way that the system feels like an extension of the user's mind. See the [MVC Pattern language](http://folk.uio.no/trygver/2003/javazone-jaoo/MVC_pattern.pdf) on Reenskaug's website. Databinding is described there as an optional add-on. So React is not necessarily contrary to MVC. – Matt Browne Jun 17 '16 at 13:03
  • Also, note that React can be used on conjunction with web components, and there are libraries to help with this, e.g. https://github.com/richardanaya/webblock/. And while React does not have 2-way databinding, it's possible to achieve a similar level of convenience with this library: https://www.npmjs.com/package/valuelink. IMO the main advantage of React is that it's a tool for creating an "immediate mode GUI" rather than a "retained mode GUI"; see https://www.pubnub.com/blog/2014-10-22-immediate-mode-user-interfaces-with-reactjs/ (you touch on many advantages of this in this answer). – Matt Browne Jun 17 '16 at 13:12
  • One thing against React, many businesses simply can't use it because of Facebook's license wording. – Joe Oct 18 '16 at 20:30
  • @Joe License issue has been resolved. Facebook re-licensed it under MIT license – Abdul Rauf Apr 04 '18 at 08:11
22

The React guys have a pretty good explanation on the comparison between React and Web Components:

Trying to compare and contrast React with WebComponents inevitably results in specious conclusions, because the two libraries are built to solve different problems. WebComponents provide strong encapsulation for reusable components, while React provides a declarative library that keeps the DOM in sync with your data. The two goals are complementary; engineers can mix-and-match the technologies. As a developer, you are free to use React in your WebComponents, or to use WebComponents in React, or both.

Erik Kaplun
  • 471
  • 4
  • 12
  • for superefficient replacement of both React as well as Web Components: https://github.com/WebReflection/heresy/ – Erik Kaplun Jan 26 '22 at 12:30
19

Polymer is awesome. React is awesome. They are not the same thing.

Polymer is a library for building backwards compatible web components.

React is the V in MVC. It's the View, and nothing else. Not by itself at least.

React is not a framework.

React + Flux + Node + (Gulp or Grunt) is more comparable to a framework, but 3 of those things aren't part of react at all.

There are many technologies, patterns, and architectural styles that react developers follow, but react itself is not a framework.

It's sad that no one took the time to say the simplest possible thing, that they should not be compared. They have some overlap, but they are more different than the same.

They both allow you to define web components, but in different ways. Beyond that they are very very different tools.

Robotsushi
  • 1,097
  • 1
  • 10
  • 17
  • Isn't React both the M and V, not just the V, since it holds and updates data state and renders fragments of html via components? – abelito Apr 10 '19 at 04:54
  • 1
    There are react state management libraries like flux or redux, but these aren't packaged with react. – Robotsushi Apr 11 '19 at 17:08
  • Oh I see, we don't consider the View data to be model data.. until it is submitted to server side. Even though React holds component state (view data), that's remains view data until submission. That makes sense. – abelito Apr 11 '19 at 18:21
  • 1
    I understand the question and a number of other answers, but not this answer. "Polymer is a library" "React is just a library" "Therefore you can't compare the two". Doesn't really make any sense to me. – River Tam Jan 19 '21 at 19:20
15

Another answer in one point specifically :

Write JavaScript in vanilla JavaScript, write CSS in CSS, write HTML in HTML.

Nothing prevents you from writing Javascript in, say, CoffeeScript, TypeScript, ClojureScript or anything else. It's purely a matter of preference.

HTML is the best DSL for static HTML documents. But it provides nothing for dynamic HTML. And in the browser, the best language to make HTML dynamic is Javascript, not pure HTML with ad-hoc Javascript DOM manipulation or template language like Handlebars that are not even half languages.

For CSS, if your CSS is static, you write it as usual. If it needs to be dynamic based on some runtime values, it's the same story as HTML : Javascript is the best way to make it dynamic.

DjebbZ
  • 251
  • 2
  • 3
  • 2
    I appreciate the answer, but that wasn't actually my point. Hopefully my edits made the question a little clearer? – CletusW Jun 04 '14 at 20:03
  • 1
    Sorry it doesn't. You can still write your style in a any styles language in a separate file. And React's JSX make it look like you're using a markup language. – DjebbZ Jun 05 '14 at 05:40
  • 3
    "Javascript is the best way to make [CSS] dynamic" - simply saying it doesn't actually explain why. – pilau Nov 25 '14 at 22:57
  • 1
    Well, if the styles/classes needs to change according to user input or business rules, just use javascript to change them. In vanilla js, you would manipulate the classList or styles properties of a DOM node. With React you can achieve the same goal manipulating the Virtual DOM. Is it clearer ? – DjebbZ Nov 26 '14 at 07:14
  • 2
    Vjeux, core contributor to React, recently gave a talk where it pushes the "CSS in JS" concept using React. I think it's interesting, you may be willing to see what it is about : http://blog.vjeux.com/2014/javascript/react-css-in-js-nationjs.html – DjebbZ Dec 16 '14 at 14:12
10

I think the biggest drawback of React in my opinion is that it isn't based on web standards. React is a very powerful tool right now, but because it circumvents so much of what the browser provides whenever possible, decisions that seemed to make sense now will likely not make sense in a few years time as the browsers' built-in facilities continue to improve. So I'd like to talk about that and how it impacts a few different aspects of web applications.

Performance

People like to argue that React's advantage is that it completely re-invents the entire DOM and event model, and the existing standard DOM is heavy and expensive and what-not, but at the end of the day I haven't found the performance of React to be better than what I can get out of a well written Backbone or Polymer application. In fact, in most of my professional experience, the performance of React has actually been a bit worse. That's not to say React is slow...It's just not the bleeding edge performance choice we all thought it was before we got our hands on it.

In rsp's answer, he points out that React's DOM model for a div is much lighter weight than the native DOM div, and that is certainly true. However, for React to be useful, that 'virtual' div has to end up becoming a real div at some point. So in my world view, it's not a matter of a React div vs a native div. It's a React div + a native div vs just a native div. The overhead of React's version of the DOM is non-trivial, and if the standards ever drop some of those unneeded attributes and allow the native DOM nodes to be much lighter, suddenly that overhead is going to seem really expensive.

In one of my previous places of employment, we had some applications in Polymer, and some applications in React. One of the early Polymer applications ended up being re-written in React because that was what the company had standard on, and based on the measurements I took the React version of this same application wound up using about 30% more memory than the Polymer version, and albeit the difference was marginal, the Polymer version rendered in less time as well. One thing to consider here is that we're talking about applications written by people, and people aren't perfect, so it might be possible that the React implementation of this application wasn't taking advantage of everything React is capable of. But I think at least some of it has to do with the overhead React incurs from having it's own version of the DOM.

React re-invents the entire DOM using its own model and then uses that for a major performance optimization. A view gets rendered into a virtual DOM, and that gets projected into the real DOM. When there's a change and the view must be updated, the view gets freshly re-rendered into a virtual DOM again, and that tree is diff'd against the previous tree to determine what nodes must be changed in the real DOM to reflect this change in the view. While this is a very clever approach to making efficient DOM updates, there is over-head in maintaining all of these virtual DOM trees and diffing them to determine what to change in the real DOM. Right now, this overhead is greatly offset by the performance benefits, but as the native DOM gets improved over time, the scale will shift in the other direction. I worry about how React apps might age, and if in 3 years time they'll be much slower than things that deal with the DOM more directly. This virtual DOM approach is a bit of a sledge hammer, and other libraries like Polymer have been able to implement very efficient approaches for dealing with the DOM in a much more subtle way.

Update for performance: One of the libraries I've stumbled across a while back does what I think is a better job of managing updates to the DOM. It's Google's Incremental Dom library, and I think the fact that it works with the dom in-place and doesn't have to create a 'virtual copy' is a much cleaner approach, with much less memory overhead. See more here: http://google.github.io/incremental-dom/#about

Declarative vs imperative components

One of the things you always hear come up when you're talking about componentizing your application is all of the benefits of your components being declarative. Inside of React's worldview, everything is nice and declarative. You write JavaScript that returns markup and React glues it all together for you. And that's great if you're dealing with a brand new application that only uses React and nothing else. You can write some component and as long as you're inside of a React owned piece of the DOM, it's as simple as putting that tag on the page to consume your component.

But as soon as you go to take those components and use them outside of React, things get a lot messier. Because the way React components are made into tags is completely outside of what web standards provide, nothing other than React knows how to give you a declarative way to consume these components. If I want to put React components into an existing Backbone view that's using Handlebars templates, you have to render a dummy div in your template with a class or ID you can use as a handle, then write imperative JavaScript to find that dummy div and mount your component into it. Got an Express.js application that's using server-side templates? Well it's that same song and dance. A JSP page? You laugh, but there's a ton of applications still using them. Unless you're some kind of startup with no existing code, you're going to have to write some plumbing in order to re-use your React components across many applications. Meanwhile, Polymer achieves components through the Web Components standard, and by using the Custom Element spec, Polymer is able to author components that the browser just natively knows how to consume. I can put a Polymer component into a JSP page, an Express.js template, an ASP.NET view, a Backbone view...inside of a React component even. Literally anywhere you can use HTML, you can consume a Polymer component. People who are engineering for reuse are looking to web standards, because standards are the contract that makes it easy to make things compatible with each other. YouTube keeps authoring more and more stuff in Polymer (source: http://react-etc.net/entry/youtube-is-being-rebuilt-on-web-components-and-polymer), and I can only imagine the standards-based aspect of Polymer is the reason why. That YouTube player in the middle of the YouTube page could be turned into a component that takes in a content source as a property, and suddenly anybody who wants to embed the YouTube player into their page can literally use the exact same player code YouTube is using, and they can do so simply by sticking a tag into their page.

Summary

I can see there definitely being some appealing aspects of React right now. If all you're using is React, you can build some widgets and some components and declaratively reuse them all over the place. But I think React would have been a lot better off if it would have used some of the Web Components standards to achieve what it does, instead of going off and building a browser within a browser and a complex mechanism to keep everything in sync.

Dogs
  • 1,166
  • 7
  • 11
6

I have not used Web Components, but it looks like they require you to add manually coded mutation logic to event handlers.

snippet from Polymer example:

 <script>
   Polymer({
     counterChanged: function() {
       this.$.counterVal.classList.add('highlight');
     },
 ...

The whole point of React is to reduce complexity by eliminating mutation logic. Instead you naïvely regenerate a virtual DOM and let React's diff algorithm figure out what needs to change in the real DOM.

rishat
  • 103
  • 4
limscoder
  • 177
  • 1
  • 3
  • 5
    Not sure where you got that example, but Polymer also discourages manual DOM mutation in favor of data-binding, including for [class names](http://www.polymer-project.org/docs/polymer/expressions.html#tokenlist). – CletusW Sep 23 '14 at 22:15
  • It's the example from the "create elements" tab on https://www.polymer-project.org 's front page. – limscoder Sep 24 '14 at 21:12
  • 4
    Wow, you're right! I guess they just wanted an example of automatic node finding. That's probably not the best one to give, though. – CletusW Sep 25 '14 at 17:09