Speedy Apps with Angular and React by Dave Smith

Speedy Apps with Angular and React by Dave Smith at ng-conf 2016.

0:00
[APPLAUSE]
0:04
DAVE SMITH: Hey, everybody.
0:05
How we doing?
0:07
[CHEERS]
0:08
Good?
0:08
Well, today I wanted to talk– oh, I really
0:11
should have turned this off.
0:12
Hold on.
0:13
Oh, I’ve got to take this.
0:15
Sorry, hold on.
0:16
Hey, Grandma.
0:19
Yeah, yeah.
0:19
Thanks for calling back.
0:21
Yeah.
0:22
So I just wanted to call and tell you,
0:24
remember how last year I called you,
0:25
and I was all happy because I didn’t
0:27
have to use jQuery anymore?
0:29
[LAUGHTER]
0:30
Yeah?
0:31
Because this Angular thing has been so awesome?
0:34
Well, now I get to use React in my Angular.
0:36
I thought maybe you’d like to know about that.
0:38
OK.
0:39
Yeah.
0:40
I– yeah.
0:42
(WHISPERING) I love you too.
0:43
[LAUGHTER AND APPLAUSE]
0:47
So I usually like to start off with a joke.
0:49
Today, I’ll do two.
0:50
I was going to tell a really hilarious one,
0:52
but I didn’t really know how you would react.
0:56
Before we talk about performance,
0:58
it’s important for us talk about what is our job as engineers.
1:02
Engineering, I believe, is when that
1:05
which is theoretically possible through science
1:09
reaches a compromise with that which is economically feasible.
1:14
And this is where we find ourselves constantly
1:16
tugging between the trade-offs of what’s possible
1:18
and what we can afford to do.
1:22
Performance is really hard.
1:24
It’s a hard problem.
1:26
In fact, this was a quote that I recently
1:31
found– I don’t think you’re measuring what
1:33
you think you’re measuring.
1:34
This is actually Misko to me about this talk.
1:39
Twice.
1:43
Here’s a question I get a lot– is React faster than Angular?
1:48
Well, the answer is very simple–
1:49
that’s a stupid question.
1:50
[LAUGHTER]
1:53
I’m not going to compare apples and oranges today.
1:56
Instead, I am going to build a whole new kind of super powered
2:01
Frankenfruit.
2:01
[LAUGHTER]
2:04
But first, I feel like I owe you an introduction to React.
2:07
Here it is in 30 seconds.
2:09
React is a web view framework in JavaScript
2:14
that’s designed to take your application state
2:16
and allow you to write code that takes that status input
2:19
and returns Virtual DOM, which is really just a set of plain
2:23
old JavaScript objects, which is then passed into React’s
2:26
Reconciling and Rendering Engine,
2:29
and then generates from that a set of optimized DOM operations
2:33
that need to be performed on browsers to make it real.
2:35
A little more detail.
2:37
The performance premise of React is
2:39
that the DOM is dangerously unperformant for engineers
2:41
to work with directly.
2:42
So instead, they give you a virtual DOM
2:44
to work on, which is an intermediate representation
2:47
of DOM.
2:47
When your application state changes,
2:50
you return new virtual DOM, React
2:53
diffs it against the existing virtual DOM
2:55
and generates performance-optimized DOM
2:57
operations that will then go to the browser.
2:59
It can do things like batching reads and writes,
3:01
which results in fewer reflows, and it can even
3:04
do cool things like generate big blocks of inner HTML
3:06
for maximum speed.
3:08
Here’s some links I’d like you to check out later about React.
3:10
So now you know a little bit about React–
3:12
[LAUGHTER]
3:14
There’s an obvious conclusion.
3:16
React everything!
3:17
Right?
3:18
Well, the unicorn grumpy cat says that’s really not
3:21
that possible.
3:21
So we’re going to just React some of the things today.
3:24
But first, I want to tell you a story with two parts.
3:26
The first part is tragedy, and the second part is glory.
3:29
We’ll start with the tragedy.
3:31
This is a piece of UI that we developed at my company
3:34
at Higher View.
3:35
It’s a table.
3:35
It’s written with Angular.
3:37
It’s NG repeated.
3:38
Our product managers came to us, as product managers are
3:40
wont to do, and they said, please
3:42
add a new column to this table.
3:44
It’s that one.
3:46
And I thought, oh boy.
3:47
We already have an NG repeat table,
3:48
and now you want us to do an NG repeat list
3:50
inside of our NG repeat table.
3:52
So I did a little bit of advanced performance
3:54
mathematics, and I came up with the following.
3:56
If I have a slow NG repeat table and I add to it a nested NG
4:00
repeat, what I get is precisely a really slow NG repeat table.
4:04
[LAUGHTER]
4:06
So I thought, React to the rescue.
4:09
Here’s a “wat” moment.
4:10
Did you guys know React stole their logo from the Simpsons?
4:12
There it is.
4:14
This is the attempt we thought.
4:15
Let’s write a directive that internally
4:17
uses React to render that list of stuff
4:19
so that it can be optimally fast.
4:20
We’ll call that directive right inside of our NG repeat markup.
4:24
Here’s what happened.
4:27
[LAUGHTER AND APPLAUSE]
4:35
It’s not very good.
4:37
Here’s why it failed.
4:38
React had no ability to batch its DOM operation,
4:41
so it couldn’t do the one thing that it’s good at.
4:43
And the reason was, it did not control the outer DOM.
4:45
And what I mean by that is that Angular controlled the tables
4:48
and rows, and then React just had to render inside
4:50
of each one of those rows.
4:51
So it ended up generating options
4:53
like this– append child react, append child react,
4:55
append child react instead of just inner HTML.
4:59
Also, I should point out, NG repeat, as we learned,
5:01
is not inherently slow.
5:02
And we ended up implementing this feature with a nested NG
5:05
repeat, and it was fine.
5:06
Then we go forward to a year into the future.
5:09
Just a few months ago– I’m going
5:11
to tell you the glory part– product management came
5:14
to us again and said, please build the following.
5:16
It’s a schedule search algorithm.
5:18
It allows users to bring up a calendar,
5:21
click a Search button, and then we’ll
5:23
start searching in their calendar for availability
5:25
to do interviewing.
5:26
Well, this sounded really cool.
5:27
But again, I started thinking about performance.
5:29
And I was concerned, because we had done apps
5:31
like this before where you have a lot of things happening
5:33
a lot at a time, which means you’re going
5:35
to have a lot of digesting.
5:36
What would happen is you’d click Search Week, all of the cells
5:38
would go into spinner mode, and then
5:40
results would start coming back from the server quickly.
5:43
And before we knew it, you’d have a performance challenge
5:45
on your hand.
5:46
We decided, we already game overed once with React–
5:49
should we insert coins to continue, or just
5:51
keep our game over?
5:53
We decided to insert coins.
5:55
And this time when we did Angular plus React,
5:58
we got a prophetic narwhal.
6:01
I’d like to show you what that looks like.
6:04
Here we have some code.
6:05
This is my app.
6:06
Instead of showing the actual app,
6:08
I’ve reproduced it in a minimal fashion
6:09
so you can just see the relevant bits.
6:11
Here we have index.html.
6:13
This body consists of just two directives.
6:16
One is called My Calendar, and the other
6:18
is called My Calendar React.
6:21
I’d like to show you what this looks like.
6:24
My Calendar and My Calendar React right there,
6:27
right now, they’re just a Load button.
6:28
When I click this Load button, it
6:30
will actually fill in the DOM to represent the calendar.
6:32
But before I do that, I want to turn on the profiler.
6:36
So I’m just going to hit Start, Load, Stop, just like that.
6:42
So now you can see visually what the calendar looks like.
6:45
It’s 24 hours tall and 31 days wide for a total of 744 cells.
6:51
And here is the profile.
6:53
If you haven’t used Chrome’s profiling tool,
6:55
I’ll tell you a little bit about it.
6:56
The horizontal axis is time.
6:58
Left is older.
7:00
Right is newer.
7:01
The vertical axis actually represents
7:03
the depth of your deepest function call stack.
7:07
For the purposes of this talk, all we really
7:10
care about is horizontal width.
7:11
The depth isn’t really that important.
7:13
I’m going to zoom in here.
7:14
You can see the Event Handler that happened here.
7:19
And what we can see if we hover here
7:21
is down below where it says aggregated total time is
7:23
about 544 milliseconds.
7:25
That’s across all of these.
7:29
Now we’re going to do the same thing in our React directive.
7:32
Just click the Load button.
7:33
I’m going to start the profiler, click Load, Stop.
7:40
Here you can see it did the same thing.
7:41
Actually, this one was 87 milliseconds.
7:43
And those numbers are a little weird.
7:45
When I’ve run this before, it hasn’t
7:46
been that slow on the Angular One side,
7:47
so I’m going to do this again just
7:48
to make sure we get good representation.
7:50
So Start, Load, Stop.
7:54
OK.
7:55
Yeah, that’s more like it– somewhere between 300 and 500
7:58
milliseconds.
8:00
So you can see why that happened is because React
8:02
was able to generate all of that DOM
8:04
by doing a single inner HTML call.
8:07
When you give a browser an inner HTML piece of HTML,
8:10
it really is the fastest it can run is about that.
8:15
That’s one thing.
8:15
Now, the next thing I want to show you
8:17
is, what happens when I click this Search button?
8:19
So what I’ve got here is a whole bunch of cells.
8:21
Each cell is independently searchable.
8:23
So I can click on it, and it simulates a trip
8:25
to the server that can take up to– let’s
8:28
see– I think I said 10 seconds, but let me just double check.
8:31
Nope.
8:32
Actually, that’s half a second.
8:34
We’ll do it again here.
8:36
So each cell can take up to 10 seconds to do a search.
8:38
You can see that 4 o’clock hour came back with four results,
8:41
and then it just randomly generates a response
8:43
with a number in it.
8:44
And I can have a bunch in flight at once,
8:46
and within the next 10 seconds, they’ll
8:48
all return with results randomly generated.
8:50
Between 0 and 10 seconds, just like that.
8:54
Now, I am using dollar timeout to do this.
8:55
So what that means is that every time a search result comes
8:58
back, my root scope gets digested, which
9:00
means Angular has to dirty check every single scope
9:02
in my application.
9:03
And since I have 744 cells inside of a nested NG repeat,
9:07
I have 744 scopes at least.
9:09
So that’s a lot of dirty checking
9:10
that it has to do in Angular One.
9:12
So let me just click this button and start the profiler.
9:19
So you can see, between 0 and 10 seconds,
9:21
each cell is slowly trickling in its results.
9:27
That’s enough for now.
9:29
Let me expand the profiler.
9:31
So what you see here is a thick–
9:33
what I like to call sequoia redwood
9:35
forest with very thick trees.
9:38
There are little gaps between the thick Sequoia trees.
9:41
And those little gaps are times when
9:42
the browser is responsive to user input
9:44
and the event loop isn’t busy.
9:45
But the times where you see the colorful areas, the trees, that
9:49
is time when your JavaScript code
9:51
is blocking the event loop.
9:52
And if you go and zoom way in here,
9:54
you won’t be surprised at what you find– 744 scope
9:57
digests inside of each one.
9:59
Now, this is my fault, because I wrote my app this way
10:02
to do dollar timeout.
10:03
Dollar timeout is not very performant,
10:04
because it assumes that anything could have changed,
10:06
so it needs to redigest your whole app.
10:09
But let’s go look at the Reactor version.
10:12
So I’m going to load it, start the profiler,
10:15
hit the Search button.
10:20
That’s probably enough.
10:22
And let’s zoom in on that.
10:24
So you can see here, it’s a different story.
10:26
Instead of a forest of thick sequoia redwood trees,
10:28
we have a forest of toothpicks, which is what you want to see.
10:31
This space between each toothpick
10:34
is time when the browser can be fully responsive to user input.
10:37
So just to compare a little more carefully here,
10:40
let’s just pick about a one-second time chunk there.
10:45
So this is from second five to second six on the Angular one.
10:48
And then I’ll do the same thing in React.
10:52
Here’s a one-second time chunk.
10:54
You can see quite a big difference
10:56
in the amount of space between each chunk.
11:00
All right.
11:00
So that’s how that looks.
11:01
By the way, I could have done some more optimization to make
11:04
the Angular One app look more like this, but I didn’t.
11:07
Because by default, we’re going to be using dollar timeout,
11:11
and this is the kind of thing you’re going to have to debug.
11:13
But let me just show you what the code looks like.
11:15
So here’s my app file.
11:18
The Angular One code, you should be really familiar with.
11:21
This is common pattern here.
11:22
We have our My Calendar directive.
11:24
Inside the My Calendar directive,
11:25
I have a nested NG repeat, and then
11:28
inside that nested NG repeat, I have a My Calendar cell
11:30
directive, which is declared a little bit down here.
11:33
And each My Calendar cell has just a couple of NGS
11:36
ifs inside of it to decide what state to show
11:38
and what should go in there, just like that.
11:40
Pretty straightforward.
11:42
Now, if I scroll down below the calendar cell one,
11:44
I’ll show you the directive that has React inside of it.
11:47
So My Calendar React was the name
11:49
of directive, which you’ll remember from the HTML.
11:51
And here’s its link function, which just does one thing.
11:55
It says react dot render, and then this weird thing.
11:59
Does anybody know what that is?
12:00
Has anyone seen that before?
12:02
This is called JSX.
12:04
And it is not JavaScript.
12:06
It is a way to easily represent HTML right
12:09
inside of your JavaScript.
12:10
And this thing is actually a React component,
12:12
which I’ll scroll down and show you what it looks like.
12:15
So here I have a calendar component.
12:19
You declare a React component by saying react.createclass.
12:21
Every React component should have a render function.
12:24
And the render function returns a bunch of HTML.
12:26
Now, it looks pretty templatey, but notice,
12:28
we’re still in our JavaScript file.
12:30
This HTML is actually not returning DOM.
12:33
This HTML– or this stuff that looks like HTML–
12:35
is actually returning virtual DOM.
12:38
And this gets compiled by React’s JSX compiler
12:42
into a different kind of JavaScript that actually
12:44
will execute in the browser.
12:45
So you can see here, this is my calendar.
12:47
My calendar is just like my angular calendar.
12:51
Instead of using NG repeat, we actually use array dot map.
12:56
So here I’ve got an array dot map over the hours and an array
12:59
dot map over the days.
13:00
And inside here, I’ve got a cell component that I’ve written.
13:03
And the cell component is another react class
13:06
with its own render function that
13:07
has a couple of if statements and returns different
13:10
HTML depending on the state of the cell.
13:13
Just like that.
13:14
All right.
13:15
So that’s actually how easy it is
13:18
to integrate a React component into in Angular directive.
13:22
Let me show you what happens when we speed things up a bit.
13:24
So right now, we saw with a 10-second random timeout
13:27
on each cell what it looks like.
13:29
If I make that closer to half a second,
13:31
you can really start to feel what things look
13:33
like from a user’s perspective.
13:36
So let’s load up the Angular One, hit Search.
13:39
Now, remember, I made it a half-a-second timeout,
13:41
so all of these should be done in half a second.
13:44
You can see it’s cooking along.
13:46
Actually, I think this is not– I think I made them in cache.
13:48
Let me try again.
13:52
That doesn’t look right.
13:57
Let’s go to the New Tab.
14:02
Huh.
14:03
Maybe that’s right.
14:03
It seems awfully slow.
14:07
Let me restart.
14:12
Wait for it.
14:15
OK.
14:19
Huh.
14:20
That seems really slow to me, but we’ll just go with it.
14:22
Let me show you the React One.
14:24
Just like that.
14:28
Let me do that again, in case you didn’t see it.
14:30
[LAUGHTER]
14:33
You had to be watching.
14:35
So the difference there is not digesting the whole world.
14:38
Because in the React app, it was easily– by default,
14:40
the design is to only really digest
14:41
the things you need to, although it doesn’t have a digest.
14:44
And in fact, the root scope digest
14:46
didn’t run at all inside the React directive.
14:48
So there you you.
14:49
So that’s kind of the difference.
14:52
All right.
14:52
So let’s go back to slides here.
14:55
There are drawbacks to using React.
14:57
First of all, you will add 500 kilobytes of code to your app.
15:00
It is not a tiny library.
15:01
Secondly, you must have a JSX build step.
15:03
You can write Reactive without JSX, but I don’t recommend it.
15:06
Thirdly, you now have two frameworks in your app.
15:08
Now, this is a problem because you have people to train,
15:10
you have developers who won’t know one or the other,
15:12
and now they might have to know both.
15:14
So it can be a problem.
15:16
Lastly, you might very well have to change
15:17
your internationalization.
15:18
We did.
15:19
We support 14 languages, and we had
15:21
to use a very different internationalization
15:23
pattern with React than we did with Angular.
15:25
React, however, does shine.
15:27
In the initial download, it does really well,
15:29
because it can batch all of the operations
15:31
to generate it really quickly.
15:32
And this is mostly thanks to things like inner HTML.
15:35
Also, after small state changes, React
15:37
is really good about only touching the parts of the DOM
15:39
that actually changed.
15:40
And it’s even really good when there
15:41
is big changes in the DOM, because it can bulk do those,
15:45
too.
15:46
React is kind of weak after there are no state changes.
15:49
If you tell React to re-render your whole app,
15:51
it will generate all of the new virtual DOM.
15:53
And in my experience, it takes about twice as long
15:55
to generate all the virtual DOM for an app of significant size
15:58
than it does to run through the digest dirty check once.
16:02
For an app I was testing with, for example, you
16:04
can get 13 milliseconds verses about 27 milliseconds in React,
16:07
which you might think is insignificant,
16:09
except 27 is greater than the 60 SPS boundary, which
16:12
is 16 milliseconds.
16:13
And so it does make a difference.
16:15
One of the strategies I use is to not
16:17
tell the whole app to re-render, but rather,
16:19
find the components that have changed
16:20
and tell those to re-render.
16:22
So that’s pretty much all I wanted to show you about React,
16:24
but I do have one more thing that I wanted to show you.
16:30
I did actually build the app in Angular 2.
16:34
Thanks a lot to the Angular team for helping
16:36
me get this working.
16:37
And I just wanted to show you what that looks like.
16:40
So first of all, I’m going to hit the Load button.
16:43
That’s actually really fast.
16:44
Hope you can see that.
16:45
Now I’m going to hit the Search button.
16:47
So you will want to be watching for this, because remember,
16:52
here’s how it looked like with React.
16:54
Just pay attention to how long it took.
16:56
This is React.
17:00
And here is Angular 2.
17:02
[CHEERS AND APPLAUSE]
17:17
[LAUGHTER]
17:18
Angular 2 is really, really fast.
17:23
You have to do your own engineering.
17:24
You need to measure, observe, and decide for your team.
17:27
Thanks very much.
17:28
[APPLAUSE]
17:37
DAVE SMITH (VOICEOVER): Hey, everybody.
17:40
You may have noticed a mistake that I made in my talk
17:42
when I was comparing the performance of Angular
17:45
2 and the React example.
17:49
The problem was that in my Angular 2 example,
17:52
the random millis function was written
17:54
to return 0 while the react function at the time
17:58
was written to return a random number between 0 and 500.
18:04
So it’s really not a fair comparison
18:06
to show the run times of the two frameworks when one of them
18:10
is set up to return more slowly.
18:12
I’m really sorry about that.
18:14
It was completely accidental.
18:16
Now I want to make it right and show you
18:17
what it looks like when both frameworks are set up to return
18:20
a zero millisecond timeout.
18:23
So here is the React example.
18:28
And I’m not even going to run the profiler.
18:30
I’m just going to let you see it visually.
18:32
So I’m going to click the Search All Month button.
18:36
OK.
18:36
And here is the Angular 2 example.
18:41
To my eye, the Angular 2 example does look a little bit faster
18:45
for this particular example.
18:48
But it’s worth mentioning that the Angular team actually
18:52
helped me optimize this.
18:53
And the React team hasn’t had a chance to look at this at all.
18:57
I wouldn’t make any kind of conclusion
18:59
about the relative performance of these two frameworks
19:01
from this example.
19:03
But I at least wanted to show that I did make a mistake,
19:07
and I did make the performance difference look more
19:10
significant than it really was.
19:12
So I apologize for that.
19:13
And thanks for being patient with me as I
19:15
work on performance.
19:16
Like I said in my talk, performance is hard.
19:19
And what I didn’t say in my talk is that I’m a gigantic idiot,
19:22
and you probably shouldn’t listen
19:24
to anything I say anyway.

 

 

AngularJS 4U is a development blog and Angular Community where you can share your latest ng development tips, articles, demos, plugins, modules and more.

Leave a Reply

Your email address will not be published. Required fields are marked *