Today we are going to dive into the Angular 2 Universal Starter Kit. If you have never heard about it it’s ok, your boss is not going to fire you tomorrow because of that (not yet). There are other Angular 2 Universal seed projects in the wild but this one is complete and very simple to start with, furthermore it’s been created by the Angular Class team, which is composed of some Angular official contributors and they have great humor (ex: this post’s thumbnail).
What is Angular Universal ?
Single-Page Applications (SPA) are great, they offer better performance and better User Experience, however they come with a price.
- Google bots are not great at indexing SPA apps (they are improving though, other search engines like Baidu are doing worse) and you will have a hard time optimising your SEO there.
- It takes a lot of time to initially load the beast.
Angular Universal solves those issues by allowing server-side rendering (SSR)!
I wouldn’t do a better job then them describing their technology’s workflow so head there to see how the magic works.
Now let’s get our hands dirty!
The architecture can be a little bit complicated at the beginning but just like the bicycle, once you get it, it’s easy.
Basically it’s a separation between client-side (app.browser.module.ts) and server-side (app.node.module.ts).
In the application, those two files look the same at the beginning but as the app evolves, they will diverge.
In app.browser.module.ts, you can only import client-side modules like the Angular 2 Bootstrap module for example whereas in app.node.module.ts you can only import server-side modules.
The only difference with app.browser.module.ts will be:
Universal Module will be composed of different modules that only work in the browser. If you create a new Angular 2 component, don’t forget to add it to the app.browser.module.ts!
The keystone of the Angular 2 Universal application is the server.ts file:
Quite a big file isn’t it?
Let’s focus on what is new here.
Let’s start by enabling the production mode. In this mode only one cycle of change detection is done. So your app is basically two times faster.
We then use the angular2-express-engine in order to render our Angular 2 app:
Angular Class good guy team added a fake server API for us, but you can create your own too:
For our app routes:
As the comments say, add one route for each client’s routes.
Finally the last important part:
We get our server-side main node module and then use it in ngApp every time that our client side routes get hit.
The Preboot Case
This preboot option here is very important. By default this option is set to false. Typo from the Angular Universal team? Too many beers at Angular Beers?
Before Angular 2 kicks in, the user can do many actions. What would happen if we don’t stock those actions? They will just disappear once the client is ready.
Let’s have a look if this feature is broken (which would explain why it’s not used by default) or not.
First thing we log the events stocked into preboot_browser.ts:
Then we add an input into our app.ts:
And we add a timeout in our client.ts:
Finally we set the preboot option to true.
As you can see, the events are stocked and the text typed is present.
If we set preboot to false, the text that is typed by the user will not be transferred to Angular 2 and will just disappear.
Google bots are great but it will take a lot of time in order to be fully SEO SPA friendly. That’s why people dedicate time in order to fill this gap instead of waiting years.
Angular 2 Universal is a mix between client and server side that can be a bit hard to understand at the beginning, just remember to put your client modules in app.browser.module and your server modules in app.node.module.
Finally use preboot to catch events from the user before Angular is ready, even though it’s not set by default to true, it’s working as it should.