DAVID EAST: I can only roll once I crack every bone in my body.
[BEEP]
Let's see if we can get this first try.
[BEEP]
Boom!
First try.
[BEEP]
First try.
[MUSIC PLAYING]
Hey, everybody.
Welcome back to the Server-side Rendering with JavaScript
Framework series.
In the last episode, we built a service-side rendered app
with Angular Universal.
And in this video, we're going to take a look at that app,
and we're going to profile it with the Chrome DevTools--
and then also profile it with webpage tests
to get a real-world situation on a low-power device on a really
poor network.
So let's dive right down into the laptop.
So here, I have a server-side rendered app
and a non-server-side rendered app.
I'm going to open up the DevTools
for the non-service-side rendered app,
and I'm going to make sure that I have the cache disabled.
And then, I'm going to do a refresh--
and we can see, we have all these assets being downloaded.
And it says our load time is 272 milliseconds,
which is pretty fast, but I'm on a really fast computer
on a really fast network.
So let's actually go up here and do some throttling.
So I'm going to throttle to regular 2G, which will actually
have us incur 300 milliseconds of latency per round trip.
So you see right here, the profile says 300 milliseconds
of latency over a 250-kilobyte bandwidth.
So now I want to go into Performance,
and this is where we can get a profile of how
our app performs on page load.
So I'm going to click this little Refresh button,
it's going to do a little bit of profiling.
And then, now it's done.
And we can see that we have all these colored bars right here.
And we also appear to have some screenshots.
And it's just a blue rectangle, because we've only
downloaded the HTML and CSS.
And if we scroll all the way to the right,
we see it takes till about four seconds
that we actually see something painted on the screen.
So these colored bars right here tell us why this is.
So you can see, we start with the HTML--
and that took 315 milliseconds to download.
Then we download our styles, which took 370 milliseconds.
But down here, we have all of this JavaScript--
we have the inline bundle, the polyfills, the vendor bundle--
which includes Angular and other libraries-- and then,
we also have our main bundle.
And you can see that the vendor bundle actually
took 2.99 seconds to download.
And it isn't until after all of this JavaScript is downloaded,
that we can go up here and make our network
requests for our data.
And you see that our fax.json call took 307 milliseconds.
And then, once that was done, we could finally render.
So this right here is a big delay in the critical path,
because our most important asset in this case
is our JavaScript, since it does all the rendering.
But because we have it set up in a way
where HTML and CSS doesn't paint anything meaningful,
we have to wait for our JavaScript
to finish downloading, parsing, and executing,
then make an API call, and then, finally render something.
So this is not the best use of the critical path.
So now I'm going to go into the server-side rendered app,
and I'm going to do the 2G throttling,
and do a performance profile.
So our app rendered in about one second,
and that's because we had our HTML server-side rendered.
But as you can see right down here,
that our HTML rendered in about 300 milliseconds,
our CSS in about 300 milliseconds,
and then we were able to paint the page.
And that's because all we need is HTML and CSS.
But that doesn't mean we're out of the woods,
because we still have to download, parse, and execute
our JavaScript-- and that happens all the way down here.
And you can see, just like with the non-service-side rendered
app, it still takes 2.99 seconds to download that bundle.
So our app is not actually going to be interactive
until this bundle downloads.
So to get a good idea of when your app is interactive,
I'm going to use a website called WebPagetest.
Webpagetest.org is an amazing tool,
where you can profile your websites
or other people's websites on real devices
on a throttled network.
Down here in Advanced Options, I'm
going to make sure that I'm testing on a mobile 3G
slow profile, which incurs 200 milliseconds
of latency per a round trip, and it gives us a bandwidth
of 780 kilobytes a second.
So I'm going to select that, put it in my URL,
and start the test.
I'm going to go and open up a new tab,
and I'm also going to profile the non-server-side rendered
version under the same profile settings.
So I'm going to wait for these tests to run,
and now that I magically fast-forward,
we're going to look at the results.
So the first one is the non-server-side rendered app.
You can see that right here we have
a couple of top-level metrics.
And so, this is the median run-- so the middle
of the road of three test runs.
So it says that the load time is two seconds,
and the first byte came in in 0.9 seconds,
and then we rendered shortly after in 1.2 seconds.
But if we look over here, there is
another number that's important, and that's
the first interactive.
And it said that it took 3.2 seconds for this website
to be first interactive, which is
much higher than the actual load time.
So if we go to the runs below, we
can see we have about the same load times.
So what we want to do, is we'll go to the Filmstrip view.
The Filmstrip view allows us to get a play-by-play of what
happened as your page loaded.
We have this top part, which is the visual loading,
and the bottom part is a timeline of the network
requests and the rendering.
So we can scroll through here, and we
can see that we actually don't see any rendering until 3.2
seconds.
So I actually can scroll back all the way to the beginning,
and we can play-by-play what happened.
So it took about 765 milliseconds for the HTML
to download.
And we know that we need CSS, as well, before we can render.
So it took about 264 milliseconds,
and then we painted something on the screen.
And then now, we're out of the woods,
because we need to download our JavaScript.
So all the JavaScript gets downloaded.
And then, once it's finished, it's
now going to go and kick off a network request for our facts--
which took about a second.
And then, now that the facts have finished downloading,
it'll render--
and then now at 3.2 seconds, we have our page rendered.
So, ideally, we wouldn't want to wait all the way to the end
here to render our page.
So even though our load time was listed at two seconds,
it's really important to monitor the filmstrip
and look at the first interactive.
So now with server-side rendering,
we're going to get a bit different results.
So this is a profile of the server-side rendered app,
and you can see that its load time is
actually about the same, if not a little slower, here
at 2.1 seconds.
And the first byte is about the same,
the first render is about the same.
But this first interactive is much, much lower
at 2.1 seconds.
And if we go down to all the runs below,
we can see the first view--
2 seconds, 2.1, 2.1--
so about the same.
So now, I'm going to click into the Filmstrip view,
and I'm going to make sure I'm at 0.1 seconds.
And let's start from the beginning.
So we're going to download the document, which
took 740 milliseconds-- which is similar to before.
And then, we're going to download
the CSS, which takes 216 milliseconds-- similar
to before.
But now at 1.5 seconds, we have our content on the page,
so the user has something to look at.
So now we're going to go and download the JavaScript
and execute it.
You can here at 2.1 seconds, the screen actually blanks out.
And that's because, at this point,
the JavaScript has executed, and it's
going to make a network request for the fax data.
So it blanks it out, and it's going
to create a new version of the app, which
is a client-side version.
So once it finishes downloading this fax.json down here
at the bottom, it will then, at 3.4 seconds, render a new page.
Now, out of the box, this is how Angular Universal behaves.
And it's not what you want, because while you
do have content for the user immediately,
there's this big chunk of time where it's just blank again.
And we can actually tell Angular Universal to not make
this request, and we can tell it to use
a cache version of the data, but that's a little time-consuming.
So if you're interested in learning how that works,
just leave a comment and I'll make a follow-up video.
But if we have this problem fixed,
you can see that we would have a page render much faster,
and we wouldn't need to make that extra network request,
so our time to interactive would be much lower at 2.1 seconds.
So with Angular Universal, we can
get a much faster first render, because we
send down HTML and CSS first.
And if we didn't have to make that extra network request,
our time to interactive would be much faster because we wouldn't
have to re-render the page.
But if you want to see how that's done, like I said,
just leave it in the comments and we'll
make a follow-up video.
So that's all for today.
If you appreciated this video, make
sure to hit the Thumbs-Up button and subscribe
for more updates in the Server-Side Rendering
with JavaScript Frameworks series, because,
next time, we're going to be taking on React.
So that's all, and I will see you all in the next video.
[MUSIC PLAYING]
Do you hear people talking, or is that just me?
OK.
I hear people talking, but if you can't hear them,
that's good.
[BEEP]
[MUSIC PLAYING]
OK.
[MUSIC PLAYING]
[BEEP]
Are we good?