Your privacy matters: This site uses cookies to analyze site usage and provide social media features. Learn More.

The Real Benefits of the Virtual DOM in React.js

April 19, 2016 in JavaScript Articles

Written by Chris Minnick


There’s some confusion and misunderstanding over what benefits the use of a Virtual DOM in React.js provides.

We’ve all heard that updating the Document Object Model (DOM) directly is inefficient and slow. However, few of us actually have the data to back it up. The buzz about React’s Virtual DOM is that it is a more efficient way to update the view in a web application, but very few of us know exactly why and whether this efficiency will result in faster page render times.

Putting aside the other benefits of using React, such as one-way data binding and components, I will discuss what exactly the Virtual DOM is, and whether it alone justifies the use of React over other UI libraries (or no UI library at all).

Why do we need a UI Library?

Two of the most important ideas of reactive programming are that systems should be event-driven and responsive to state changes.

The DOM’s user interface components have internal state, and updating the browser isn’t as simple as just regenerating the DOM whenever something changes. If Gmail did this, for example, you would be constantly annoyed when the entire browser window refreshed in order to display a new message, wiping out the email you were composing.

The statefulness of the DOM is why we need user interface libraries and solutions such as key/value observation (which is used by Ember among others) or dirty checking (which is used by Angular). UI libraries handle watching for changes to the data model and updating the correct part of the DOM when these changes occur, or watching for changes in the DOM and updating the data model when they occur.

This type of watching and updating is called two-way binding, and it can often make working with user interfaces very complex and confusing.

What makes React different?

What makes React and its Virtual DOM so different is that it’s simpler than other approaches to making JavaScript reactive from a programmer’s perspective. You write pure JavaScript that updates React components, and React updates the DOM for you. The data binding isn’t intertwined with the application.

React uses one-way data binding to make things simpler. Every time you type in an input field in a React UI, for example, it doesn’t directly change the state of that component. Instead, it updates the data model, which causes the UI to be updated and the text you typed into the field appears in the field.

Is the DOM slow?

Every talk and article about the Virtual DOM will point out that although today’s JavaScript engines are extremely fast, reading from and writing to the browser’s DOM is slow.

This isn’t exactly true. The DOM is fast. Adding and removing DOM nodes doesn’t take much more than setting a property on a JavaScript object. It’s a simple operation.

What is slow, however, is the layout that browsers have to do whenever the DOM changes. Every time the DOM changes, browser need to recalculate the CSS, do layout, and repaint the web page. This is what takes time.

Browser makers are continually working to shorten the time it takes to repaint the screen. The biggest thing that can be done is to minimize and batch the DOM changes that make redraws necessary.

This strategy of reducing and batching DOM changes, taken to another level of abstraction, is the idea behind React’s Virtual DOM.

How Does Virtual DOM Work?

Like the actual DOM, the Virtual DOM is a node tree that lists elements and their attributes and content as objects and properties. React’s render() method creates a node tree from React components and updates this tree in response to mutations in the data model, caused by actions.

Each time the underlying data changes in a React app, a new Virtual DOM representation of the user interface is created

This is where things get interesting. Updating the browser’s DOM is a three-step process in React.

  1. Whenever anything may have changed, the entire UI will be re-rendered in a Virtual DOM representation.
  2. The difference between the previous Virtual DOM representation and the new one will be calculated.
  3. The real DOM will be updated with what has actually changed. This is very much like applying a patch.

Is the Virtual DOM Slow?

One would think that re-rendering the entire Virtual DOM every time there’s a possibility that something has changed would be wasteful — not to mention the fact that at any one time, React is keeping two Virtual DOM trees in memory.

But, the truth is that rendering the Virtual DOM will always be faster than rendering a UI in the actual browser DOM. It doesn’t matter what browser you’re using: this is just a fact. But it’s also sort of irrelevant.

The problem is that your users can’t see the Virtual DOM. It’s like owning 10,000 tacos in another county. Sooner or later, you need have the tacos delivered, and that can be expensive and slow.

Sticking with the taco analogy (because, why not?), is it faster to have all of the tacos shipped to you at once, or to calculate the difference between how many tacos you need and how many tacos you own and just ship bare minimum number of tacos? It’s certainly less expensive to ship 4 tacos when you only want 4 tacos.

The next question is: how do you go about ordering the tacos? Do you say, “Send me 4 tacos” or do you say, “Here’s how I’d like my taco situation to look. You work out the details.”

The 2nd approach is how the Virtual DOM works. You write the code to make your UI look how you want it to look, and the Virtual DOM works out the difference between that and how it looks now and only updates what needs to be updated.

React does this magic by attaching attributes to elements in your document and manipulating them individually (using these very specific ID attributes) after doing the diff to determine what needs updating. The Virtual DOM inserts additional steps into the process, but it creates an elegant way to do minimal updates to the browser window without you having to worry about the actual methods being used or even what needs to be updated and when.

Let’s See Some Numbers!

I’m not going to do benchmarking tests. A number of other people have created different tests to figure out whether React’s Virtual DOM approach is faster. The most frequent conclusion seems to be that it isn’t, unless it is, but it doesn’t really matter because the tests aren’t realistic.

The Virtual DOM adds a layer of scripting on top of whatever optimizations the browser is already making in order to make these minimized DOM manipulations transparent to the developer. This additional layer of abstraction makes React much more CPU-intensive than other methods of updating the DOM.

Here’s a “Hello, world!” example that uses native JavaScript DOM manipulation:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8" />
    <title>Hello JavaScript!</title>

</head>
<body>
<div id="example"></div>
<script>
    document.getElementById("example").innerHTML = "<h1>Hello, world!</h1>";
</script>
</body>
</html>

And here’s how you would do the same thing in React. Note that we need to include React, React DOM, and babel, which is responsible for converting the XML-looking code in the render() method into vanilla JavaScript.

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8" />
    <title>Hello React!</title>
    <script src="build/react.js"></script>
    <script src="build/react-dom.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>
</head>
<body>
<div id="example"></div>
<script type="text/babel">
    ReactDOM.render(
    <h1>Hello, world!</h1>,
            document.getElementById('example')
    );
</script>
</body>
</html>

The native approach is always going to be faster. And just for kicks, let’s look at the proof.

Here’s the timeline for loading and rendering the direct DOM manipulation “Hello, World!” page (in Chrome).

Load Graph

And here’s the timeline for loading and displaying the React “Hello, world!” app in the same browser.

Load Graph

Notice that everything is essentially the same, except for time it takes to do the scripting. React is slower than using DOM methods directly, and by a lot! But, how does it compare to jQuery?

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8" />
    <title>Hello jQuery!</title>
    <script type="text/javascript" src="scripts/vendor/jquery-1.12.3.min.js"></script>

</head>
<body>
<div id="example"></div>
<script>
    $(document).ready(function(){
        $("#example").html("<h1>Hello, world!</h1>");
    });
</script>
</body>
</html>

Load Graph

jQuery’s total time to display the simplest Hello, world application is about 50ms slower than pure JavaScript, and both are about 3 times faster than React.

So, clearly, if it was just about how fast they are, pure JavaScript and jQuery win easily.

However, this is just common sense. Using a library is slower than not using a library. And creating an in-memory representation of the DOM before actually manipulating the DOM is slower than just manipulating the DOM directly, when it’s done correctly.

Now that we have the obvious out of the way, let’s discuss exactly how you can make using the Virtual DOM faster.

How to use the Virtual DOM

My “Hello, world!” examples are unfair to React because they only deal with the initial render of a page. React is designed for managing updates to pages.

Because of the Virtual DOM, each change to the data model can trigger a complete refresh of the virtual user interface. This is very different from systems used by other libraries, which observe aspects of the document and update them when necessary. The Virtual DOM often actually uses less memory than other systems, because it doesn’t need to hold observables in memory.

However, there are inefficiencies when you’re comparing two entire virtual DOMs each time an action occurs. The CPU requirements can be formidable for complex user interfaces.

For this reason, React developers can’t be completely passive when it comes to deciding what to render. If you know that a certain action won’t affect a certain component, you can tell React to not analyze that component looking for changes — saving significant resources and significantly speeding up your application. Demonstrations of React’s performance often include raw numbers showing high CPU usage followed by the dramatic improvements that can be realized with good development practices such as memoization.

The truth is, there may be no way to actually figure out if using Virtual DOM is faster than an approach that updates the DOM directly, because it depends on a million different factors, but mostly it depends on how well you optimize your application.

This isn’t surprising or revolutionary. Any tool is only as good as the person who’s using it. What React and the Virtual DOM give us, however, is a simpler way to think about updating the browser. This simplicity can free up significant mental resources and make optimizing the user interface easier. This is where the real benefits — both in performance and productivity — lie in React.


Author: Chris Minnick, one of Accelebrate’s instructors.

Accelebrate offers private React.js training for groups and instructor-led online JavaScript classes for individuals.


Written by Chris Minnick

Chris Minnick

Chris has authored and co-authored over a dozen books including titles in the For Dummies series, as well as several books teaching kids to code. Chris specializes in JavaScript technologies and writes and maintains courseware that’s used for training software developers at some of the largest companies in the world.
  



Contact Us:

Accelebrate’s training classes are available for private groups of 3 or more people at your site or online anywhere worldwide.

Don't settle for a "one size fits all" public class! Have Accelebrate deliver exactly the training you want, privately at your site or online, for less than the cost of a public class.

For pricing and to learn more, please contact us.

Contact Us

Toll-free in US/Canada:
877 849 1850
International:
+1 678 648 3113

Toll-free in US/Canada:
866 566 1228
International:
+1 404 420 2491

925B Peachtree Street, NE
PMB 378
Atlanta, GA 30309-3918
USA

Subscribe to our Newsletter:

Never miss the latest news and information from Accelebrate:

Microsoft Gold Partner

Please see our complete list of
Microsoft Official Courses

Recent Training Locations

Alabama

Huntsville

Montgomery

Birmingham

Alaska

Anchorage

Arizona

Phoenix

Tucson

Arkansas

Fayetteville

Little Rock

California

San Francisco

Oakland

San Jose

Orange County

Los Angeles

Sacramento

San Diego

Colorado

Denver

Boulder

Colorado Springs

Connecticut

Hartford

DC

Washington

Florida

Fort Lauderdale

Miami

Jacksonville

Orlando

Saint Petersburg

Tampa

Georgia

Atlanta

Augusta

Savannah

Idaho

Boise

Illinois

Chicago

Indiana

Indianapolis

Iowa

Ceder Rapids

Des Moines

Kansas

Wichita

Kentucky

Lexington

Louisville

Louisiana

Banton Rouge

New Orleans

Maine

Portland

Maryland

Annapolis

Baltimore

Hagerstown

Frederick

Massachusetts

Springfield

Boston

Cambridge

Michigan

Ann Arbor

Detroit

Grand Rapids

Minnesota

Saint Paul

Minneapolis

Mississippi

Jackson

Missouri

Kansas City

St. Louis

Nebraska

Lincoln

Omaha

Nevada

Reno

Las Vegas

New Jersey

Princeton

New Mexico

Albuquerque

New York

Buffalo

Albany

White Plains

New York City

North Carolina

Charlotte

Durham

Raleigh

Ohio

Canton

Akron

Cincinnati

Cleveland

Columbus

Dayton

Oklahoma

Tulsa

Oklahoma City

Oregon

Portland

Pennsylvania

Pittsburgh

Philadelphia

Rhode Island

Providence

South Carolina

Columbia

Charleston

Spartanburg

Greenville

Tennessee

Memphis

Nashville

Knoxville

Texas

Dallas

El Paso

Houston

San Antonio

Austin

Utah

Salt Lake City

Virginia

Richmond

Alexandria

Arlington

Washington

Tacoma

Seattle

West Virginia

Charleston

Wisconsin

Madison

Milwaukee

Alberta

Edmonton

Calgary

British Columbia

Vancouver

Nova Scotia

Halifax

Ontario

Ottawa

Toronto

Quebec

Montreal

Puerto Rico

San Juan

© 2013-2019 Accelebrate, Inc. All Rights Reserved. All trademarks are owned by their respective owners.