Lesson Description
The "Render Modes" Lesson is part of the full, Advanced Angular: Performance & Enterprise State course featured in this preview video. Here's what you'd learn in this lesson:
Alex explains client-side, pre-render, and server-side render modes, their trade-offs, and demonstrates pre-rendering pages to improve performance and user experience in Angular SSR.
Transcript from the "Render Modes" Lesson
[00:00:00]
>> Alex Okrushko: So let's just leave it as is with the event replay, and let's create some server routes. We don't need any files, we have our server routes, server routes here. Let's create some server routes. We're going to first create the path, the initial path. Let's create the new file, new. The initial path, so for our homepage. For the homepage, we'll say the render mode is render mode pre-render, so it has three modes: client-side, pre-render, or server-side.
[00:00:48]
What client-side does is basically what we do today, which is on this path, don't server generate anything, don't do anything on the server-side, this path is 100% should be generated on the client-side, just like we have without server-side rendering. We can do the server-side and it'll say, hey, don't pre-render anything, but every time user gets to that path, generate that DOM on the server first.
[00:01:20]
So you have that index HTML shipping to the application. You're basically at runtime, at request time, you generate that DOM. Or you have a third mode, which is pre-render, so when you build the application. Pre-create something already for it, so you already have index HTML pre-created at build time, not at the runtime when the request comes in, when the request comes in, it's like, oh, I have something for you already created, it's like fast, super fast, yes.
[00:01:53]
So can you talk about hypotheticals as far as like when you might want to use the server option versus the client option? Yeah, so the server option could be beneficial again, there's few trade-offs, for example, you can pre-render on the server when your data is highly dynamic, but you, the data that you have there, for example, I don't know, your product list changes all the time, you might want to delay the client-side and precreate that, get that data into the DOM, and then ship it to the client-side, and then user immediately sees the whole page.
[00:02:37]
The disadvantage of that is that user doesn't see anything until you're done with creating the app. So there's sometimes a tradeoff between this, you might want to pre-create most of it on the server-side, you can still have some dynamic data that's super fast APIs, but then the main products that are continuously changing would be deferred, and then you get the initial DOM into the browser, and then you do the API call finally to fetch the data, so, in overall time, it'll be longer.
[00:03:13]
But from the user perceived performance is like, oh, you have something to look at already, and then this is loading events or something like that, loading products, right, so there's that. Well, pre-render is really cool for stuff that doesn't change too much. For example, our events, we don't have a new events every second, right, that created or removed or something like that, we can pre-render the events and we're going to see how we can do this for this page, and then when you request that page, you have the events already, but then at the background, it'll still go and fetch the new list of the events and say, hey, is it different from what I see.
[00:04:03]
Using track, we'll see that, hey, maybe there's a new set, so you might be seeing the stale data. But you'll get the latest data in. There's even better approach for this. You know, when you change events, you know when you create events. So what you can do when you create an event in a database, you will automatically call Angular to rebuild the bundle with the latest data, that's like a nice workaround for this, so you do get not the stale data, but it was still current, and you will rebuild the Angular and redeploy that, right, like you rebuild that.
[00:04:46]
That's very powerful way to do it as well, because you know when the data is changing. Again, if it's highly, highly dynamic data and a product list that there's many decisions why, what's going on there, right? So, you can't really prevent it, then you can defer it either to, ah, you could do the server-side render or pre-render only the shell parts of it, that's not dynamic data.
[00:05:17]
So that you can see instantly. And then dynamic data within that, you can defer, and I'm going to see this a little bit later. Today. All right, hopefully that answers it, this is really powerful stuff, right, it's really cool stuff. One thing to note. If you worked with, I don't know, like Next.js or other apps, they have like server components or reactions, that one's continuously streaming, so all requests, even if once you load the page, they're still going to the back end and it just gets you some new components, cached, pre-rendered, whatever, in Angular SSR, this is for the initial request.
[00:06:07]
Once you get the response back, all of it becomes client site. So it's no longer going for server for those specific pieces. Which just makes sense because one of the purposes of SSR is to really improve the initial page load. Good, see a lot of nods, okay, good. All right, let's see if it makes any difference. So we'll pre-render our homepage.
[00:06:48]
And I'm going to show you something really cool here. Then for our path, which is our event ID, event ID. Let me initially render mode, I don't know, render server, for example, render server-side, we can get through this and then for the path. For this is the intermediate step, that what you see here is our final, but this is the intermediary, so, and then for admin.
[00:07:25]
We're just like, okay, we're never going to be rendering this render mode client. Right, this is three different render modes. All right, we have our server, okay, good, good, good. That's awesome. So for our server to work, I have to start my backend separately now. Because I'm going to be building the new bundle for our SSR application.
[00:07:58]
So let me start the server, now it's let's say, it's serving all those things, because some of those things would be pre-rendered. For it to pre-render correctly, it needs to access this data at the build time. If we don't have a back end running for the build time, then we'll have basically no data for it, so we'll pre-render with no data.
[00:08:25]
Cool, and now, also in our package.json, something that was added here is like serve SSR DevFest manager, and then using the Node to go for this DevFest manager on the server-side and serve it. We've seen before, right, when we build our application, we have browser right now, we're going to add both browser and server chunks. So let's build this application, we're going to be building it the same way we've been building before, which is the ng build.
[00:09:10]
And you build or npm run build. Either one. So it's building the application. And now we see we have the browser. And we have the server. And we can see it created all the chunks, it created even assets, this is our, some of the pages that we have, you can see it's basically we'll export all of this immediately. Let's see it in action. Let's see it in action, and for us to see it in action, we'll have to serve this, right?
[00:09:58]
So this will be npm run serve SSR DevFest manager. And this will be basically running our Node.js application that serves Angular and SSR, right? Cool, and notice here we'll also have it running on the 4000 server port, so just to keep it different from the Angular application, just to make sure that we have it at a different port. Let's take a look at the app.
[00:10:32]
So again, this is also just previous performance number 83, we're trying to beat that. Let's see if we can do that, so in our. Here we will open localhost 4000. And you probably saw these. Let's see, let's see it again, see it again in action. Boom. What happened here? Our app, let's take a look at the structure here, our localhost. What do we have here?
[00:11:12]
CSS critical CSS is inline, all the things are inline. But apart from all the CSS stuff, we also see our entire application is here, here it is, our entire DOM is here. Our entire DOM is here. Right? So it is really, really powerful. Right, very powerful stuff. Let's check our Lighthouse score. What's happening here? Pretty good, right? We are at 99, so it prebuilt prefabs those nice images as well in a small format and it's super high performance now.
[00:11:59]
So this is our homepage, is 100% pre-rendered with the data that was available at build time, so these events were basically part of the DOM response immediately. Now, let's look at one of those details and what we have them with server-side rendered. So this is server-side rendered, but again, if we navigate right now it's client-side rendered, right, but we need to refresh this page, hard refresh to see it going back to the server first, let's see it.
[00:12:37]
And you can see it renders on the server and then immediately level, so there was no loading here anymore because the data is packaged on the server-side, and again, if we see that is our request here. That's our 401, you see all of this start generated on the server when we send the request. So all of this was there when we sent the request.
[00:13:09]
Serialize the data for us as well, all of the stuff that when we did the request, so we have app details already completely filled here. See, all the data, it's already pre-rendered. But not pre, sorry, it's server-side generated and provided by the back end. And then if we go to the admin page. Yes, we do need to have it set item for true local storage.
[00:13:53]
So I can get it by the guard. And I'll refresh it again, you see. You get certain things, here it is, create. What we get back here is the app that has nothing in it. The app root. Right, and it was client-side generated with the chunks that are provided with JavaScript. So those are quite significant pieces. Now for this event, right, there could be multiple events, we can.
[00:14:35]
And right now, we're just server-side generating them if somebody just lands here, right? We can do better. We can do better. In fact, let's just do the comparison. So Lighthouse, right now, server-side generator, let's see if we can have a new report for this. There'll be issues with images, our images are full size, but again, this is like 74, right?
[00:15:09]
Our image is full size, this image is not optimized with ng-optimized image, so we got a little bit punished for that as well, but we see the 74 report. What we can do as well with Angular. As in our app config server here. Let me just remove that with my server routes. In my server routes, I can help us a little bit, so I can say, hey, I have those different IDs.
[00:15:40]
What if I'll pre-render this instead, but there's so many IDs which ones to pre-render. Well, we can have, we can provide this async even function, async because it can basically go to the database and query what you have the top five visited pages, events, for example, whatever you want to do, right now in this, I'll just return immediately, but we can specify the pre-render params.
[00:16:23]
Which params I want to pre-render by itself, and in my case, I'll just return an array of ID one and ID, for example, two, so my first and second page will be generated at prebuild time at build time. So event one and event two, you can see right now on my server-side, they're not here. They're not here. Let's see if this changes, so I'm not going to stop my server, no, the Express server running.
[00:17:19]
I'm going to build it again. Boom, we have event one. And event two, they are pre-rendered now. That is very powerful, so now when I'll start serving this on my localhost 4000. And I hard refresh this page. Boom, instantly available. Event two. Instantly available. Event three. Not so much, now that one's the server-side rendered and pushed to me as well.
[00:17:43]
Right, so you can see the difference. So for the pages that have parameters, but frequently visited, you can prebuild them as well, so they're available for the pre-render. SSR was not really popular, I think in Angular, but now it becomes more and more popular, and now you can deploy this application, because it's basically Node.js application, it does require the server to run this, right?
[00:18:13]
You can deploy it to many things, like Next.js has default to Vercel, but you can also deploy this to Firebase hosting, they support all of this, they can pre-render your stuff as well, it's really good. And the reason I mentioned Firebase quite a lot, I used to work for Firebase, I was in the console team there, so I'm very familiar with a lot of tooling and all the great services that they provide with an extremely generous free tier.
Learn Straight from the Experts Who Shape the Modern Web
- 250+In-depth Courses
- Industry Leading Experts
- 24Learning Paths
- Live Interactive Workshops