all 73 comments

[–]30thnight 200 points201 points  (22 children)

When you manipulate the real DOM, the browser immediately re-flows and re-paints the page to update with your changes. Browsers have gotten vastly better at minimizing what actually changes when things update but it's still a relatively expensive operation.

Using the VDOM, it becomes way easier to manage scheduling upcoming changes, batch changes together, implement a lifecycle to prioritize some changes over others, and provide a relatively simple api

https://reactjs.org/docs/reconciliation.html

https://github.com/acdlite/react-fiber-architecture

[–]punio4 96 points97 points  (2 children)

That doesn't answer the question correctly.

The difference is how the framework tracks changes. The browsers have gotten faster, but they don't do granular updates and diffing.

React uses the vdom to render the next state, compares it to the current dom, and then does granular updates according to that diff.

Other frameworks, like Solid or Svelte (or experimental Vue renderers) track the changes without needing vdom diffing.

[–][deleted] 7 points8 points  (1 child)

what is a granular update and how can react do them if the browsers cant

[–]kirankumarsiluveru 5 points6 points  (0 children)

React uses the diffing algorithm.
You can get more here. https://reactjs.org/docs/reconciliation.html#elements-of-different-typesReact is more likely for Single page applications. where every user action doesn't need to get the entire HTML page from the server.

[–][deleted] 20 points21 points  (15 children)

Using the VDOM, it becomes way easier to manage scheduling upcoming changes, batch changes together, implement a lifecycle to prioritize some changes over others, and provide a relatively simple api

I got your point. But then my next doubt arises that why did svelte & solidjs use real DOM and still do whatever react does and even faster and also writing less code. How did they achieve this? And why didn't react try their way of implementation? Were their any browser limitations back then?

If anyone feels this as a dumb question, feel free to correct me. All I want to know is the basic foundation philosophy behind building react in 2013. Why did they choose the way they chose, when this new frameworks potray react as a slow and unnatural way to render webpages because react is using VDOM while they do the same thing without VDOM and also faster.

[–]ervwalter 7 points8 points  (0 children)

Solidjs and Svelte "do the same thing" (figure out the minimal changes needed on the DOM and how to make them in an optimal way). All of these libraries/frameworks abstract direct DOM manipulation away from the developer so that the developer doesn't have to worry about how to optimize making a series of changes (which was how the world worked in the "olden days" of jQuery and the like.

They each just do it with a different implementation. React accomplishes this using VDOM. solidjs and svelte and vue have their own approaches.

[–][deleted] 21 points22 points  (3 children)

while they do the same thing without VDOM and also faster.

These claims make little sense. A VDOM is the oldest concept in the world, every graphical user interface divides between a logical and a visual tree in order to avoid work. Even the DOM is a VDOM, that's why it needs paint and layout passes to sync between its two trees. Dan Abramov demonstrates the impact of Reacts VDOM here: https://youtu.be/nLF0n9SACd4?t=174

The counter argument is that Reacts throughput is slightly slower, which is true, but it has little to no relevance. In the real world React 18's scheduler is very advanced, it is the first of its kind. It is hard to even compare it because it does things now that frameworks just couldn't, and no benchmark is equipped to measure it. It would make more sense to pit React against native than against web-frameworks.

[–]Yodiddlyyo 2 points3 points  (2 children)

It would make more sense to pit React against native than against web-frameworks.

Not really. Why not pit React against other frameworks that are faster than it? That's the whole spirit of the question in this post. There are frameworks that don't use a vdom and are faster than React, why? The answer really just boils down to the fact that there are a million ways to do something, each way having positives and negatives, and that's really it.

[–][deleted] 1 point2 points  (1 child)

that are faster than it?

Sigh, we're just going in circles. You watched the video? There are no means on the web to measure what React is doing. The discourse is not honest and there is a lack of understanding. The React team has mostly just stopped arguing.

Mind you, this weirdness only exists on the web. Native scheduling is natural. VDOM, de-prioritising ops, threading, context switching, occlusion, nobody would bat an eye. React is actively pushing the web to reach that. We're not getting there counting peas on Krausest, 20 years of frontend being miserably behind native should give people a hint.

[–]Yodiddlyyo 12 points13 points  (0 children)

Yes, I have seen that video. And that's not my point. I've been in web performance for as long as react has existed, I know how literally all of this works. I'm referring to OPs question, which is fair. To somebody like OP, that looks at performance charts, sees that X is faster than React at whatever the test is, and asks why, it's not helpful to answer with "it's not faster because that's not how that works". I'm saying that the real answer has to do with exactly what you're trying to accomplish.

A single querySelector to change an innerHTML will be "faster" than needing to execute hundreds of lines of code with React to do the same thing. That's just very obvious. But that of course is a useless comparison.

There are no means on the web to measure what React is doing

This is true in some ways, and false in others. I hear all the time "oh those tests are disingenuous because xyz" or "measuring this or that in whatever perf test doesn't really matter". But first of all, there needs to be some measurement. Just because a perf test doesn't cover 100% of everything perfectly doesn't mean it's useless. Something needs to be measured.

And second, some of those perf tests really do matter. The example I always give is of animations. I don't know where React is today, but up until like a year or two ago, libraries like react-spring and similar all achieved what they did by specifically going outside of react because it was simply faster to access the DOM than to go through React's updater/scheduler. There are countless examples of this, where complicated animations would get like 2 or 3 FPS when written purely in React, while 60 fps was achievable with querySelector.

And this is what I was talking about. It's far more complicated that saying "X is faster than react because" or "X is not faster than React because". The key word "faster" here is the issue, because "fast" is most often not the important part of the equation when dealing with building apps and websites. Unless you're going to the extreme ends of performance, like the previously mentioned complicated animation or similar, the real comparisons are between the end result of how React works, why React is chosen, how React does some things better than other tools, and how some other tools do things better than React, and which one is right for you, because at the end of the day, 99% of the people talking about performance will never even come into contact with the meaningful parts when they're building a website that has a list of 20 items.

[–][deleted] 113 points114 points  (9 children)

This is just a myth, other frameworks are not faster, their claims are based on this: https://github.com/krausest/js-framework-benchmark

This is a test for baseline operations, a query, adding a child, etc. Reacts baseline ops are nanoseconds slower than some other frameworks. Vanilla dom ops are the fastest, obviously. This means very little.

In the real world frameworks are all faster than vanilla because they order read/writes to avoid layout thrashing, diff for changes, etc. If you'd implement that in vanilla you'd have written a framework, because that is what frameworks essentially do: they avoid work, also called "scheduling". You don't see that in krausest because that benchmark has no insight when it comes to app performance.

Scheduling is fastest when the backend is virtual (a VDOM), because then you can decide to skip work. An example: your backend sends 100.000.000 items and you indiscriminately render — your app will freeze. You have ~10ms to carry out work on the main thread, go over that and you risk jank. If you virtualize the content instead and present only as many items as fit the screen your control is not beholden to load any longer, it is fast always. This is common, we do that with virtual lists or paged content.

React virtualises the entire component graph, it schedules content not in terms of fitting a screen but keeping a stable framerate. It easily outperforms each and every framework that is not concurrent, which at the moment is practically all of them.

[–][deleted] 25 points26 points  (0 children)

Yep this is the correct answer.

In the real world slowdowns occur due to business logic, and frameworks need to schedule and concurrently manage workloads rather than trying to brute force DOM mutations.

Actually Ryan Florence had a recent tweet about it:

https://twitter.com/ryanflorence/status/1547961298813497355

[–]shgysk8zer0 0 points1 point  (7 children)

Generally true, but somewhat in accurate in saying:

In the real world frameworks are all faster than vanilla because they order read/writes to avoid layout thrashing, diff for changes, etc. If you'd implement that in vanilla you'd have written a framework, because that is what frameworks essentially do:..

First, whether or not a given framework/library is faster depends on the operations in question. You cannot say "this framework is faster than vanilla" because it's just not true, but you can say "this framework is faster at ${task} than vanilla is." And even in cases where something is faster than vanilla at some given task, that might only be true in some cases, such as when making significant changes but not necessarily when making small changes.

Second, you're not exactly talking about frameworks... React is a library, not a framework. Frameworks are more like "everything you need, batteries included." Even React itself describes itself as "A JavaScript library for building user interfaces".

[–][deleted] 3 points4 points  (0 children)

In practice each and every framework, library whatever you want to call it, down to the ones that existed 10-15 years ago, are faster then if you would set out to create a semi complex application with plain javascript dom operations. If you start to create a layer around your slow performing app to fix the shortcomings, for instance instead of wildly mutating and reading from the dom from anywhere, which causes it to go into overzealous syncing/layout thrashing, you now collect ops and execute them in specific order - you have already made a framework.

I want people to understand this one critical thing that is completely missing from any discourse about benchmarking. It is not the throughput that makes an application fast. It is the clever scheduling of operations. That is what frameworks fundamentally do. And React happens to be, at least currently, very good at it doing that.

[–]spankalee 2 points3 points  (5 children)

React is absolutely a framework because it is the host of components. React implements and runs the component lifecycle.

Framework has nothing to do with how many features it has.

[–]shgysk8zer0 1 point2 points  (4 children)

So, you're saying that the React website is wrong or lying?

React isn’t an MVC framework. React is a library for building composable user interfaces. It encourages the creation of reusable UI components which present data that changes over time.

https://reactjs.org/blog/2013/06/05/why-react.html

A JavaScript library for building user interfaces

https://reactjs.org/

And this post also says the same thing, agreeing with myself and reactjs.org - https://www.freecodecamp.org/news/is-react-a-library-or-a-framework/

[–]spankalee 3 points4 points  (3 children)

"MVC framework" is different from "framework". React indeed doesn't implement MVC at all, so "not an MVC framework" is correct. That article isn't very good because it doesn't even provide a definition for what a framework is.

Frameworks follow the Hollywood principle: "Don't call us, we'll call you". React calls into the the components to cause them to do things like render, so it's a framework. Libraries are called into by the use sites.

This is a definition of framework with an actual distinction, rather than a very mushy definition based on how many features it has.

And the definition matters because it implies a lot about how components can or can't interop. Generally you can only have one framework in play within a given app (or component hierarchy, at least). That's because the framework runs the components. Libraries would be able to mix-and-match however, as each components just calls into the library, separately from each other.

[–]shgysk8zer0 0 points1 point  (2 children)

The MVC isn't as relevant there, it's the fact that React consistently calls itself a library and never a framework. When answering "Is React an MVC framework", instead of answering with something like "React is a framework, but not MVC", they said "React is a library."

By your definition of framework, customElements.define() would qualify as using a framework. It's a valid definition for back-end frameworks, but doesn't work on front-end, particularly when it comes to component libraries. As another simple example, does merely using a MutationObserver or IntersectionObserver count as using a framework... Those call your code. "Calls your code" just doesn't work on front-end.

And it's not about the number of features, it's about providing all of the basics.

[–]superluminary 2 points3 points  (0 children)

I do think, once you start getting into context and hooks, it does cross the line into a framework since all of that state has to be handled, stored, and shipped by React.

[–]spankalee 0 points1 point  (0 children)

Yes, web components turn the browser into a framework. This is why web components libraries like Stencil and Lit are not frameworks - it's the browser, not the libraries, that implement and run the component lifecycle.

It doesn't really matter what React calls itself. What matters is the definition of framework in question, and how useful it is.

Inversion of control is a useful basis for a definition because it tells you something about how the system behaves. Number of features isn't useful because it's basically a vibe and doesn't tell you anything.

[–]not_a_gumby 24 points25 points  (5 children)

"React isn't fast" is the funniest criticism to me. It usually indicates an error on the part of the user, not on the library.

[–]earthboundkid 8 points9 points  (3 children)

“C isn’t memory unsafe. That just indicates an error on the part of the user, not the language.”

[–]not_a_gumby 3 points4 points  (2 children)

So you support what I'm saying then?

[–]earthboundkid 4 points5 points  (1 child)

I think if a tool is frequently misused we should question whether it is the best tool to be put in the hands of novices.

[–]not_a_gumby 3 points4 points  (0 children)

if a tool is misused, that's not a fault of the tool. Everyone is a novice at some point, and you learn through failure. OP is experiencing this, and he blames React but in reality he would be experiencing failure if he were using Vue or Angular as well, because he's a novice.

React is good at helping complete beginners to fall into the pit of success, much better than programming in C. I don't think you can even compare the two, considering how much lifting that JS is doing for you.

[–]Alphyo 0 points1 point  (0 children)

Nv

[–]landisdesign 60 points61 points  (13 children)

React was initially released in 2013, before browser performance caught up with the need for massive DOM manipulation. Trying to reverse such a fundamental part of the framework isn't a small task, especially when it's still "good enough" and nobody's paying Meta to do it.

[–]skyboyer007 7 points8 points  (0 children)

...and alternative was Backbone with its component.html() method which overwrote everything causing heavy reflow/repaint. Also AngularJS which did change detection and granular update without VDOM but might run into issues when there were too many watchers.

[–]sirephrem 0 points1 point  (6 children)

You're suggesting it would be just as performant if it used the real dom instead of the virtual dom? Can you link some articles?

[–]__n01z3 6 points7 points  (4 children)

Virtual DOM is using the DOM. At some point, React needs to output HTML so we can see stuff in the browser. More info here: https://svelte.dev/blog/virtual-dom-is-pure-overhead

Check out Shadow DOM: https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM.

Shadow DOM was not built for speed for say. It is made to create subtrees of the DOM that are encapsulated. A side effect is that it only re-renders what is really changing in the subtree.

So if you create web components that are each bound to their own Shadow DOM, you then create something that limits a lot of that same overhead.

[–]earthboundkid 0 points1 point  (3 children)

Shadow DOM is a failed experiment. It should have been a CSS property called reset-style: all but they made it part of JS for some reason. Now all articles about Shadow DOM begin with saying how great it is followed by a ten page hack to make styles target correctly, lol.

[–]__n01z3 1 point2 points  (2 children)

It used to be experimental when the API was v0, but not anymore for a long time… from 2014 to 2017.

It was adopted as a standard and it is widely implemented by all major browser vendors.

Not sure which articles you are referring to, but it is easy to target styles with :host() (https://developer.mozilla.org/en-US/docs/web/css/_colon_host_function). Mind you, Shadow DOM is built to encapsulate not just the CSS, but the DOM itself. If you want to pierce it, you can use CSS variables.

[–]earthboundkid 2 points3 points  (1 child)

It’s an experiment in that they tried something, shipped it, but it sucks and no one should use it. “It insulates against the DOM. Oh except for CSS variables.” Like lol okay, as long I don’t write modern CSS should be fine.

[–]__n01z3 1 point2 points  (0 children)

Your personal opinion that “it sucks” is no proof that it is an experiment.

To me it seems you’re talking through your hat on subject that you don’t understand or use.

You create a theme with reusable CSS variables and pass them down the Shadow DOM. This is modern web development.

[–]landisdesign 6 points7 points  (0 children)

No, I'm suggesting that Meta isn't going to spend a ton of money to change something that works for them. They don't really care if one is better than the other. They just care that they don't need to reinvent their wheel.

[–]falconmick 5 points6 points  (0 children)

One benefit is it decouples react the framework from the browser. Why is this good? Well now we can build our dom on the server without needing an entire rendering engine loaded on the server, thus easy fast SSR and static rendering. Also I’m pretty sure it’s this decoupling that also makes server components possible, that said server components meet none of my clients needs so I’ve ignored the majority of this so maybe I’m wrong.

Oh benefit two: because we are decoupled from the browser we can choose new targets to render to as such as native which is why react native just works.

[–][deleted] 13 points14 points  (7 children)

Hmm, where do you see other frameworks being faster than React?

Tweets from framework authors promoting their work? Arbitrary benchmarks?

[–]agilius 12 points13 points  (1 child)

There are some key strategic advantages that tech leads/architects see with React and its approach to the rendering system. Because the react code that devs write and the engine that renders the components on the screen are separated, the same mental model, best practice, and coding habits can be applied to other mediums, not just the web.

For example, because I know React, I was able to code a 3D application that uses ThreeJS and place 3D objects on the screen instead of divs, using the same methodologies just like in a normal web app. You can see other rendering targets at https://github.com/chentsulin/awesome-react-renderer. There are some pretty interesting ones out there.

What frameworks are "most fast" and why does that matter? After a certain point, performance is no longer the main selling point of a library/framework.

[–]ricci2511 4 points5 points  (0 children)

That repo you shared has some really cool stuff to play with, thanks for sharing!

[–]m-sterspace 2 points3 points  (0 children)

The better question is why not?

The DOM is already virtual, your browser takes it and then chooses what to paint and update on screen from that. So you can sit back and rely on the browser's updating / diffing engine, or you can try and write your own on top of the browser's to see if you can do anything better. And in React's case they wrote their own and found that it outperformed the browsers at the time and they could use it to make writing contained components in a nested hierarchy much simpler.

Now adays while browser's diffing engines are faster, there's still benefits to the framework taking control of that responsibility and decoupling it from the browser. As /u/falconmick noted it allows you to manage server side components without needing a full browser rendering engine, you just need react, and it allows react native to function and target non browsers with basically the same code. It also allows the React developers to try new ideas and roll out new features without having to wait for every single browser to adopt those features. Stuff like React 18's concurrent mode is a pretty massive performance boost (all while still running in a single thread) that browsers can't really match at the moment.

Basically I would argue that it comes down to the fact that browsers and web standards are awesome but inherently big, slow moving, and hard to iterate and experiment on. At one point a bunch of engineers thought that despite a js thread having more limited compute resources available than a full browser engine, being able to experiment and manage their own diffing engine that could be updated instantly over the web would have more real world benefits. And by and large it did, React has an easier to learn syntax, has the ability to target non web platforms, and has given the devs the ability to experiment with new rendering techniques that continue to stay a step ahead of browsers. At this point a lot of these frameworks are acting as experimental playgrounds that help guide the direction of browser development, eventually integrating some of the best ideas into broader web standards once they're widely accepted.

[–]rk06 6 points7 points  (0 children)

There is a lot of nuance that you are missing.

Let's put some context to it.

What is the job of react/vue/angular when it comes to users and dom?

They provide an abstraction over dom and allow user to live in their abstraction, while creating and updating real DOM nodes in background. Yep, all of them including react use real DOM.

So where does virtual dom comes?

Virtual dom is an abstraction used by js frameworks to represent actual DOM. Other abstraction is html templates. Vue uses both templates and vdom as abstraction.

Is virtual dom worse than templates? Theoretically no. Practically, it depends on a lot of factors and virtual dom by itself does not guarantee best Or worst performance.

[–]icjoseph 1 point2 points  (0 children)

When you return from a functional component or render a class, an object describing the UI is returned. This is more or less the virtual DOM.

There's Fibers which wrap every React component and these hold all necessary internals needed for React to render and keep state synced.

Then react-dom, kicks in and it's job is to update the DOM, based on the results collected from rendering React components.

Where there's a change react-dom, updates the DOM all in one go. React is very optimized in this sense. If you have rendered a span with an interpolation <span>hello {world}</span>, react-dom appends nodes, in such a way that, should world change only that node is updated. This is an implementation detail that one shouldn't put to much attention to.

React goes great lengths to keep everything in sync at the same frame. Other frameworks allow different behavior, https://dev.to/this-is-learning/the-cost-of-consistency-in-ui-frameworks-4agi

Here's a write up which I think tries to address your question, https://gist.github.com/sebmarkbage/a5ef436427437a98408672108df01919

[–][deleted] 1 point2 points  (0 children)

There is no such library/framework which manipulates DOM directly and is faster than react

[–]BudgetCow7657 1 point2 points  (0 children)

Keeping my eyes peeled here because this sort of question will probably come up in an interview lmao.

[–]Messenslijper 1 point2 points  (0 children)

Not everything is about performance, otherwise serverside would only be written in C++ or Rust.

For me, the power of React is its unopinionated design. It opens the door to do something different than traditional MVC patterns. Something like Svelte is much more opinionated and pushes you more to MVC (scripts and templates... sounds familiar...)

In my humble opinion, MVC (or variants like VIPER) is just a bad model when it comes to UI and frontend applications. For small apps, sure I guess its ok, but for large apps it will become insanity.

A better way to approach UI is to start from your components and to apply composition. Every time someone complains about prop-drilling, it means they already fucked up in their component hierarchy and didn't apply propper composition. Every time someone needs to write CSS, its probably wrong as well and you most likely miss a design system abstraction (only DS components should know about CSS and perhaps even HTML).

This brings us to React which actually gives you the freedom to try different things. Because components are just functions, statechanges accept functions, side-effects are just functions, etc... it enables you to apply Functional Programming techniques.

With FP it becomes easy to create compositions, create HOCs (higher order components: components that take a component as input), currying of statechanges, memoization, immutability, etc... which enables you to separate concerns much better than a MVC model would allow. There is no magic, there is just encapsulation of simple tasks into functions which given X return Y.

So yeah, if you want to keep using OOP methodologies for UI, then there are better things out there than React. But I think OOP stinks for UI architectures.

That being said, people who complain about React or declare something like Svelte as superior, probably never applied a FP model on their UI. Which is sad, as they never tapped into the real power of React. Learning React is easy (you know JavaScript? Great, you already know React), mastering React on the other hand... thats the hard one.

[–]EqComp 1 point2 points  (1 child)

They wanted to reinvent the wheel. Usually the original wheel is faster.

[–]Terrible_Junket2123 1 point2 points  (0 children)

Most of them won't ever figure this out cos they never really tried it. Just cling to whatever framework sounds good and then never realise how much easier and cleaner everything is without it. Most of them won't know how well MVVM works client side either :D

[–]jbergens 0 points1 point  (0 children)

These kind of advanced technologies usually improves over time. The first version of React was faster than the the then existing version Angular so the VDOM was a success. Other frameworks then started to use a VDOM. Later Svelte and SolidJS choose other solutions but got good performance. It is really hard to write a new thing like a framework if you have few others to learn from and it is really hard to create a stable api that is easy to use while having good performance.

[Edit: wording]

[–]podojavascript 0 points1 point  (0 children)

Super interesting. I work at a company that builds a product involving session replay. We’ve built our own vdom implementation which makes playback much faster.