In this tutorial, we are going to learn how to integrate your Angular-CLI application with Angular Universal.
Before going into the actual coding part, lets understand what exactly Angular Universal is and how it works.

These days websites are amazing, they are rich and using a lots of Javascript code to generate their pages. Mostly Single page applications (SPA) frameworks are probably getting attention in the Javascript Market in the past years. Handling most of the data processing on the client side, boiler-plating the content on every page, maintaining the “state”, and omitting the overhead latency on switching pages are just some of its net benefits.

But, we have got a small problem, the application has to be indexed by Search engines.
Many search engines and social networks expect plain HTML to utilise the meta tags and relevant page contents. They can not determine when the javascript framework completes rendering the page. As a result they get served with the incomplete HTML content which is very useless to them. This behaviour even gets more painful when you people try to share the website link and you see an image like the one below when they do.

seo-broken-img
image is taken from https://scotch.io/

So, to address this, our application has to be rendered on the server side as well for search engines and social networks. SSR is a reliable, flexible and efficient way to ensure all search engines & social networks can access your content. Here comes the Angular Universal.

What is Angular Universal?

Angular Universal is the standalone project the Angular team is working on to make building universal apps a smooth experience. Its main purpose is to allow server to process angular code and templates. It loads our app on the server first, and then drops it to the browser once ready.

Here are some benefits of adding universal(SSR) into our app.

  • Facilitate web crawlers (SEO) – All your routes are crawlable and understandable for search engines and social networks.
  • First time users of your application will instantly see a server rendered view which greatly improves perceived performance and the overall user experience.
  • All the first HTTP requests are made on the server side and users should not wait for them on the client-side.
  • Improves performance on mobile and low-powered devices

The below video demonstrates the difference of initial page rendering and perceived page load time when SSR (aka Angular Universal) is used. The SSR version on the other hand, the users will instantly see a server rendered view.

Screen capture demonstrating the difference in initial page rendering and perceived page load times for non SSR (left) and SSR (right).

Getting Started

Generate a new project using Angular CLI

Install the following dependencies for SSR

Prepare our app for server side rendering (path: src/app/app.module.ts)

First we need to call BrowserModule.withServerTransition method. This method will tells angular, that we are using server side rendering and it expects an object with a key called appId. You can enter any string here.

Next, create a app.server.module.ts which is similar like app.module.ts file
path: src/app/app.server.module.ts

Create a main.server.ts file in this path src/main.server.ts to export our server module.

Next, create tsconfig.server.json file for the server in this path src/tsconfig.server.json

Just copy the contents of tsconfig.app.json file to tsconfig.server.json file and change “module” to “commonjs” and add angularCompilerOptions code and set entryModule to AppServerModule.

Create a second app for server in the CLI

We need to tell the CLI about all the changes, we have made, for it to work properly. Furthermore, we are going to create a second profile for the server bundle. The cli will then generate that bundle, containing only the code we require on the server for rendering.

Now, lets the CLI create our bundles, run the following command to see if it builds correctly.

The above command will produce “dist” and “dist-server” folders in our root directory. Here you can see we added output-hashing to none to the server bundle. It’s important here, this generates a clean (main.bundle.js) file without any hash.

This (main.bundle.js) file exports module called AppServerModuleNgFactory that we are going to load in our server.js file. This is the module we can use to pre-render the whole thing.

Now lets create our server.js file in the root directory.

Now our server.js is ready. lets add some scripts to our package.json to build our project.

build:universal will first build the client app, then build the server app.
serve:universal runs the build:universal command first, then runs the server.

Lets run the npm run serve:universal command from root directory.Now, the server will be listening on http://localhost:3000.

Browse this http://localhost:3000 link and  inspect the page and click on the view page source to see the rendered html by the server.

Basically, when you run ng serve command, your application will render on the client side, but when you run npm run serve:universal command, the application actually renders at server side(not a browser), and thats how search engines and social networks understands your content.

Thats it. You can refer the below github link to see the full code.
https://github.com/sivagrid/angular-server-side-rendering