Video details

Wagner Maciel: Angular Universal & Our New Prerenderer


Wagner Maciel

Get ALL the ng-conf: Hardwired videos for FREE at
ng-conf is a three-day Angular conference focused on delivering the highest quality training in the Angular JavaScript framework. 1500+ developers from across the globe converge on Salt Lake City, UT every year to attend talks and workshops by the Angular team and community experts.
Follow us on twitter Official Website:


Hello, everyone. My name is Wagner Maciel and welcome to this session of N.G.. Com. Today we're gonna be talking about Angular Universal in particular. We're gonna be going over the basics, as well as some of the latest features released in version nine. So a little bit about myself. I graduated from New York University this past May. I moved from New York to California in September to join Google and I joined the angular team. Only this past November. So I'm relatively new to both software development and to this community. But I'm so thankful for this community. It's very apparent what a great community it is. So what is angular, universal? And you are universal at its core, is a toolkit that allows you to do server side rendering and pre rendering for your angular apps. We're going to discuss pre rendering later as it's one of the new features released in version nine. But server side rendering has been a staple of this project from the beginning. So why use server side rendering? Generally, there are three main reasons why you'd want to use server side rendering on your app. The first being to show the first page quickly. eBay actually found that a one hundred millisecond improvement in their search page load time led to a two point five percent increase in their add to cart count, which is huge. And US developers, we often tend to forget about the milliseconds. Ah ah ah ah. Users certainly don't. It's critical to user engagement. The next reason why you'd want to create a universal version of your app is to improve performance for weaker devices. If I'm doing a lot of scripting in the browser on the client, then I'm relying heavily on my end users devices. So rendering an app in the browser is going to put a more of a strain on their device. And these devices aren't always reliable. They can be low powered or or mobile devices. So rendering on server helps to alleviate some of that strain. The last reason why you'd want it and want to use server side rendering is to facilitate Web crawlers. Google, Bing, Facebook. All these companies use Web crawlers to understand what the content of your application is and then index it and make it searchable to the rest of the web. And if you're doing a lot of rendering client side, it can be difficult for these Web crawlers to understand what is going on in your app versus if you send over a static page, which is what server side rendering allows you to do. Now, let's hop into a demo. This is all better shown than explained. We're going to happen to a demo that X because that shows us the basics of angular universal. So I'm going to start off here by joining Engy New. This is going to create a brand new project, I'm going to call it, and Universal Demo. And we don't need angular routing. And CSX is gonna be just fine for this demonstration now. And we knew all it's doing is creating a brand new angular app and we're naming it Engy Universal Demo. And hopefully using this simple app, we're gonna be able to demonstrate all three of those bullet bullet points, facilitating web crawlers, improving performance by reducing scripting on the client. And also that first content ful paint. How quickly we can show it. So we're gonna give us a second here while it finishes up installing my node modules. Just be patient here for a minute. If this doesn't finish up soon, I'll just. OK. All done. So now see into my app. And first thing I'm going to do here is I'm going to run Engy Ad and Universal Flash Express engine. Let me clear this up so it's a little bit more apparent. And this is going to install the energy universal schematic. And basically all that means is it's going to create a couple of files and update a couple of other files. And doing so is going to setup our application for server side rendering as well as pre rendering. And if you if you had a previous version of Engy Universal installed, you'd run the same command, but just instead of ad, you'd update. So energy update and Universal Flash Express engine. And actually, while this installs, there's one other change I want to make to this app, and it's an index of ETM L. I'm going to add a script here, and all of this script is going to do is log the value of the first content full page to the console. You can find the script that it's pulled from Web dev. It's all it's doing is just log on when that first content will paint shows. So jumping back to the terminal, we see that this is done. I'm actually I'll clear this up and run, npm run, start to start up. This is gonna start up a client side rendered version of our app. And I'm also gonna run NPM Run, build SSR, make this full screen for us and NPM run, serve SSR. And this is gonna open up the server side rendered version of our app. Actually, it's going to NPM Allenville Necessar is going to compile our client bundle as well as our server bundle and then NPM run serve. SSR is going to use those to service and render our application. And it looks like our client side version is already done compiling. I can go to local post forty two hundred here and I'm going to open up the console here in my dad's tools so we can take a look at that first content ful paint. And if I navigate a local host forty two hundred we see that it takes about seven hundred and forty milliseconds for the first ten full names to show. And on subsequent loads it's hanging out at around three hundred and twenty ish 315. And we'll wait for the server side rendered version of our app to finish compiling and then starting up so that we can juxtapose those two. Shouldn't be much longer here. Looks like we're up to our up to the end. Yeah, great. So now we'll navigate to local host four 4000. And opening the concert console. We see that the first one takes only three. And then subsequent loads are down to about 70, which is substantially less, less, significantly less than our client side version. The next thing I want to take a look at is the if we hop over to the performance tab and we click on Start Profiling and Reload page. Well, wait a second, what this is going to show us is the amount of scripting going on on the browser. So here we see client side. We have two hundred and thirty six milliseconds of scripting versus on our server side rendered at. We run the exact same diagnostic. We see it's only 90 milliseconds, so substantially less. And remember, this is such a basic app. This is just the app that you get from one engine. If you have a more complicated site, say like a blog, a blog site or something like that, the performance benefits could be way greater. Now, the last detail that I want to go over from that last bullet point, facilitating web crawlers while this app, how close these dev tools so we can get a better view while this app looks totally fine to me and you and we can interact with it just fine if I view the page source. We see that all we have here is approve and nothing else inside of it. We have the head information from here, the script that we added. But inside of our body, we have approved and nothing else. And that's because all of the content of our application is being populated by these scripts. So if I look over at the page source of our server side rendered app, we'll see. There's much more going on here. It is way easier for a simple Web crawler to understand what's going on. All of our C assesses here. And then down here, we have our e-mail. We see approved. And then all of our content is there. We have toolbar banner. So on and so forth. So that's it for the basics of angular universal. Now that we understand those, let's get into some of the new features that were released in version like. In particular, lie reloading for SSR and pre rendering. So life could reload. What this does is it automatically recompiling the client and server bundle every time that you make a change and you save. So similar to command. NPM run, start. It'll refresh everything for you and recompile things for you. And free rendering fear and being is something that I actually had the privilege of working on. It generates and saves Statik pages to the file system. And it does so at build time. So you can have these files that contain the static version of your site of your page. And you can just serve those using either a C.D. N or a very simple server. So, again, let's hop into a demo so we can understand these even better. OK. So we're gonna be using the same same project from our basic demo, the schematic is already installed. The universe schematic. And so we can just run NPM run dev SSR so that we can get that live code reload. With us, with server side rendering, we'll just give this a minute to startup. And once this is done, we'll navigate to local post forty two hundred. OK. And yet we have an app. It looks totally simple and regular. We can see that server side rendering is going on by taking a look at the page source. We see that all of our application content is here. It's not just app route, as it usually would be. But the difference between just regular server side rendering. And this is now as a developer, when I go to make a change, let's say instead of app is running, I want to say app is running with love code reload and I save. We'll see that first day Rican files and then in the browser it reloads for us, which is great, just that much easier. I'll actually do that one more time in case you didn't catch it, because the reload was very, very quick. I'll just, I guess, put anything you see here, Rican. And then in the browser it reloads by itself. And so that's the simple NPM run Devore's Asare Life Code Reload with and Universal Version nine. Now for the last demo for the pre render builder, I created a simple, a simple app, but that's a little bit more complicated. It's a poke index app that when you navigate through a Pokemon I.D., these ideas are just numbers from, I believe, one to a hundred. It'll load, it'll fetch that Pokemon and then it'll display its name as well as the image corresponding to it on the browser to get give you a feel for that. Well, actually, we can just start up a server here. Yeah, well, we depending on what route we navigate to, it's gonna be a different Pokemon every time. And so this is a perfect use case. We'll go to locals. Forty two hundred here. I already have one here. Seems this is a great use case for the pre render builder. I'll go to one bulbasaur. We'll go to five million hundred. So since we have all these routes that are very simple. These are these could be just static pages. They've been written as an angular app, but they don't need to be rendered server side and they don't need to be. Every time a user makes request and they don't need to be rendered on the client. These can all be cached as just static files. So here's the solution for that is and universal. All you have to do is go to the Anglo-Dutch Jason file and at the bottom of the file, see, it's just all the way at the bottom and just scroll down. You'll find the pre render builder defined here and inside the options you'll see roots. Now, all you need to do is just define what routes you want to pre render. Actually, you can even not define some of them inside of my routing module. I believe I have one explicitly stated. So then, thanks to guest parser, that the pre render builder will actually be able to extract that route. And we don't even need to write it. But if you don't if you do wanted to say, well, that feature you can just write guess routes and set that the false. And that's and it won't do any extraction for you. So all you have to do, the simple command to pre render these two routes is npm run. Pre render. Now we'll give the second. It is going to build your client and server bundle every time that you do this because it wants to have the latest version of your app. It doesn't want to pull and try to render using an outdated dist so it rebuilds it just to make sure. We'll give this a second here and watch it while it builds close to the pre rendering, the rendering of your roots and saving it to the filesystem is actually very, very quick. And this this is all the actual building. I'll make this full screen to you is linear time and you'll see that these roots show up in an in not the right order. And this is because the roots are being rendered in parallel. So while this is linear, this is going to be way, way were optimized. It really depends on how many species you have at that point. So we can see that these are being written to dispatch a demo slash browser and then the route name. So if I open up my file system and I go to this demo browser, we can see that we have those three files here. And it's defined in a folder that's named the same as the root slash index at A.T.M.. And most citizens are going to be really good about this. They're good at figuring out. Oh, if I have a file folder that's the name of this route and a user requests it, I can just handed the index on e-mail from that folder. And so c.D ends like Firebase are great at handling that for you. So in an ideal world, your server want to even get pinged for this. It will just be taken care of by the CBN. So what if I actually want to render those 800 rounds that I'm capable of rendering for this app? Sure, you can write them into this array over here. But that's a bit cumbersome and we recognize that. So the solution we came up with is you can define route's file and then just point this using a relative Yoro. In this case. We have roots fash file defined. And this is just a bunch of roots separated by new lines. And so you can auto generate this file however you like. And all you gotta do is point to it. But Stasch file takes time. And again, the super simple command for this and VM run pre render. And I'll close this small screen. We're gonna wait here while this branders, the build time should be linear. So it's gonna be the same as any other time you run this. But the parallelization for the actual rendering shouldn't make the eight hundred routes versus 300 asby like not that much of a difference. So hopefully what we'll see here is that the hundred votes are rendered and seconds. I'll give this a second to build. There we go. Have hundreds of routes rendered and not like maybe five seconds. So don't be afraid to use this as a solution for your app. If you have hundreds or even thousands or even tens of thousands of routes that you want to pre render. I'm sure this tool is capable of handling it. And now if we want to actually view these, we can run NPM run, serve SSR. I'll clear this. It's a little bit more obvious. And we can do this because the server and client bundle are built already by the pier under builder. We got a localized 4000 now and we go to one site and next highest mill. Again, if you were using a CBN, you wouldn't have to write the slash and text based e-mail. But the easy way to tell that this is a pre rendered page is by just looking at the bottom of the elements tag of the elements tab and seeing that there's this little comment at the bottom that marks those pages pre rendered. So it's great for testing and we can, of course, verify that all the way up to eight hundred slash next e-mail is being pre rendered. So that's all for this talk. Thank you so much. I hope you learn something about energy universal. And I really hope that you're able to apply these features and use and universal in your application.