100 days of Angular 2 - Day 11: Bring in Angular Universal

I've been very intrigued by the promises of Angular Universal. The idea of running Angular 2 on the server to render the page and serve that to the user is crucial for search engine crawlers. Since many of them do not execute JavaScript*, the page will appear broken and incomplete, so search engines have a hard time properly crawling and indexing these rich, interactive, single-page apps.

Also, if you link to page on Facebook / Slack / Twitter / some other social site, they send a crawler to create a "snapshot" of the page so it appears next to the link. Same as the web crawlers, these do not execute JavaScript and that preview will look broken if that page is part of these rich, single page apps.

How do I use Angular Universal?

If you don't care about the initial page load speed, search engine optimization, or social links, then Angular Universal is not worth your time. For example, if you have a corporate application that lives behind a login screen, you may not care about SEO, and your app wouldn't ever show up in your friend's Facebook feed because your friend wouldn't be sharing it there.

However, I have been building social apps, and most of my traffic comes in via Google search results. For me, it's worth bringing in Angular Universal into my project.

So I headed over to Angular Universal page and clicked on the 'Get Started' button which took me to the quick start.

It's a little odd that they still suggest to use typings, since the new, preferred way of declaring types is to use npm's @types. The Angular 2 Webpack Starter they reference does not use typings.

I already have an Angular 2 app, so I didn't use the Angular 2 Webpack Starter. I had some of the dependencies already, but I did need to install angular2-universal and preboot.

I already had a server.ts file that I created on day 10, but just to get something running, I copy + pasted the server.js they listed on the quick start and tried to fire it up.

Okay, let's try

Okay, so that didn't work... After some Googling I'm not sure that their quick start would ever work.

Let's abort out of the quick start and head over to the GitHub repository. They have a link to the documentation and guide.

They mention there's an Angular Universal Starter, but after cloning it and looking through it, there's a lot going on. Just opening up the package.json is overwhelming with the number of prebuild / build / clean steps, each with a bunch of different options.

It's also worth pointing out the @types listed in the dev dependencies, which means they're not using typings so I am not sure why the official quickstart still has them listed.

Okay, to recap, the quickstart is outdated and doesn't work, and the universal starter is incredibly overwhelming. It assumes a lot about the architecture and it would take me a lot of work to fold my current project into the starter project.

Node.js and Express

I already have an Angular 2 app, so the first step for me is to copy the webpack.config and tsconfig.json files from the starter app into my app root directory.

I had no issues just replacing my tsconfig.json file with the new one, but I already spent a lot of time setting up my webpack configuration.

Back on day 3 I spent time initially setting Webpack up, then splitting out dev and prod settings on day 4. I further modified my Webpack settings on day 5 to proxy requests to api/ to my backend in my development environment. So I can't exactly just copy and replace the webpack.config settings from the Angular Universal project into my own.

But looking at the webpack.config.js from Angular Universal is... a bit overwhelming. I'm not a Webpack expert so it's not very clear to me what's relevant for Angular Universal and what is just relevant to how the starter project is architectured.

Then to add more confusion to the mix, there's a separate webpack.prod.config.ts to understand.

Okay, maybe for now I should tuck all of my webpack settings (from days 3, 4 and 5) away for a moment and copy over webpack.config.js from Angular Universal to try and get something working.

However, the Webpack starter assumes all code is located in src/, but my project is not structured that way. So I need to modify the lines in the webpack.config.js so it references my client code located at client/ and server code located at server/.

Next it says

Copy the scripts, dependencies and devDependencies from the Universal Starter package.json into your local package.json file

Oh no, this is what I was trying to avoid.

I can't possibly need all of these scripts right now. I'll copy over just a few of them:

I am not sure why I'm getting red squiggles for the modules, as they're listed in the package.json and there aren't any issues locating the module if I try to compile the file to JavaScript from TypeScript.

Anyways, the next step is to create my top level NgModule on the server side like this:

Err, wait, I don't know what they're trying to say. But I did add the UniversalModule to my app.module.ts and also my main.ts