WARNING: Both ReactJS and AngularJS have changed in the time since I last looked at this demo. I am not ReactJS developer; but, I have done my best to update the ReactJS portion to use the latest ReactJS 0.14.7 and vanilla JavaScript classes instead of the former React.createClass() approach. That said, I am still using the 0.13 JSXTransformer so that I can keep the entire demo on the same page. My assumption is such that using the JSX transformer will only affect the initial page load but should become irrelevant after that. Of course, I am not entirely sure that this is true.

I have also put the Angular 2 library into "production mode" in order to disable the various assertions that it makes during the application life-cycle. I am doing my best to create an even playing field for the two portions of the demo.

The demo, itself, has not changed. I am presenting the user with a filter form and a grid of 10,000 items (1,000 rows with 10 columns). As the user changes the filter query, matching cells within the grid are highlighted. There is also a link to unmount and remount the grid in an effort to separate update time from DOM (Document Object Model) creation time.

When we last explored this comparison, ReactJS was the clear winner in all categories of performance, though I always found the AngularJS code easier to reason about. With Angular 2 Beta 3, the performance is split. ReactJS is still clearly faster when it comes to the initial rendering and the re-mounting of the grid. But, I am pleased to say that Angular 2 Beta 3 is clearly faster when it comes to applying the dynamic filter to the existing grid.

// I repopulate the grid with data. This will help separate processing

// performance characteristics from page-load processing.

function remountGrid() {

vm.grid = generateGrid( 1000, 10 );

vm.dataPoints = ( vm.grid.length * vm.grid[ 0 ].items.length );

vm.visibleCount = 0;

vm.form.filter = "";

}

// I clear the grid of data. This will help separate processing

// performance characteristics from page-load processing.

function unmountGrid() {

vm.grid = [];

vm.dataPoints = 0;

vm.visibleCount = 0;

vm.form.filter = "";

}

// ---

// PRIVATE METHODS.

// ---

// I generate a grid of items with the given dimensions. The grid is

// represented as a two dimensional grid, of sorts. Each row has an

// object that has an items collection.

function generateGrid( rowCount, columnCount ) {

var valuePoints = [

"Daenerys", "Jon", "Sansa", "Arya", "Stannis", "Gregor", "Tyrion",

"Theon", "Joffrey", "Ramsay", "Cersei", "Bran", "Margaery",

"Melisandre", "Daario", "Jamie", "Eddard", "Myrcella", "Robb",

"Jorah", "Petyr", "Tommen", "Sandor", "Oberyn", "Drogo", "Ygritte"

];

var valueIndex = 0;

var grid = [];

for ( var r = 0 ; r < rowCount ; r++ ) {

var row = {

id: r,

items: []

};

for ( var c = 0 ; c < columnCount ; c++ ) {

row.items.push({

id: ( r + "-" + c ),

value: valuePoints[ valueIndex ],

isHiddenByFilter: false

});

if ( ++valueIndex >= valuePoints.length ) {

valueIndex = 0;

}

}

grid.push( row );

}

return( grid );

}

}

}

);

</script>

</body>

</html>

While I am new to Angular 2, I am also quite the noob when it comes to ReactJS. And, this is the first time that I have ever even used ReactJS 0.14.x. So, hopefully I didn't screw this up too much or include code that puts ReactJS at an unfair advantage.

Here is the ReactJS 0.14.7 code:

<!doctype html>

<html>

<head>

<meta charset="utf-8" />

<title>

Rendering Large Datasets With ReactJS 0.14.7

</title>

<link rel="stylesheet" type="text/css" href="./demo.css"></link>

</head>

<body>

<h1>

Rendering Large Datasets With ReactJS 0.14.7

</h1>

<div id="content">

<!-- This content will be replaced with the React rendering. -->

</div>

<!-- Load scripts. -->

<script src="../../vendor/reactjs/0.14.7/react.min.js"></script>

<!--

CAUTION: Using the JSXTransformer for in-browser transpiling - this is deprecated

and not recommended with 0.14.7. But, this should only affect the initial page

load, not the post-rendering performance (my assumption).

-->

<script src="../../vendor/reactjs/JSXTransformer-0.13.3.js"></script>

<script type="text/jsx">

// Demo has to extend Component since its a stateful component.

Demo.prototype = Object.create( React.Component.prototype );

// I manage the demo.

function Demo( initialProps ) {

// Call the super constructor.

React.Component.call( this, initialProps );

var vm = this;

// I provide the initial view-model, before the component is mounted.

vm.state = {

grid: generateGrid( 1000, 10 ),

form: {

filter: ""

}

};

// Expose the public methods.

vm.render = render;

vm.remountGrid = remountGrid;

vm.setFilter = setFilter;

vm.unmountGrid = unmountGrid;

// ---

// PUBLIC METHODS.

// ---

// I render the view using the current state and properties collections.

function render() {

// Calculate how many data-points are being rendered (ie, how many tables

As someone who is infinitely more familiar with AngularJS, I still find the Angular code both easier to read and to reason about (when compared to ReactJS). I still think that React's lack of constructs for things like ngFor / ng-repeat require the developer to create an unnecessarily large number of tiny components. Or, to use .bind() during iteration which is a "code smell" to be avoided.

That said, I am definitely excited that AngularJS is clearly making improvements in performance. And, from what I've heard in various podcasts, the Angular team has more performance tweaking ahead of it in the roadmap. As far as I'm concerned, the future of Angular 2 is bright!

Reader Comments

Thanks :) I would like to add one more facet to the demo which someone suggested on twitter - randomly sorting the values. It wouldn't make a difference pre-rendering; but, I'd like to add a button that would sort the rows in reverse order to see how _existing_ DOM elements are effectively moved around.

I added a "Reverse Grid" link in the demo, for both Angular and React. Clicking that link reverses both the columns AND the rows in the grid, completely inverting it. This operation can be up to 2x faster in React. React definitely still wins when it comes to creation and movement of DOM elements.

After talking to Misko Hevery, I realized that my "reverse" action was breaking all the object identities. As such, the reverse action was basically doing the same thing as a re-mount action (which was not my intention). After switching to an in-place reverse of the grid:

... the speed of the reverse action is much faster. ReactJS is still a bit faster for me (averaging between 160-180ms), but Angular 2 is also quite fast (averaging between 200-230ms). But, this is much better than the 300ms I was seeing before this commit.

I am the co-founder and lead engineer at InVision App, Inc — the world's leading prototyping,
collaboration & workflow platform. I also rock out in JavaScript and ColdFusion 24x7 and I dream about
promise resolving asynchronously.