Server Side Rendering: Why and How using Angular CLI

Siv Vanapalli
js@imaginea
Published in
4 min readApr 19, 2018

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, let’s understand what exactly Angular Universal is and how it works.

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

But, SPAs have a small problem when it comes to getting 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 useless to them. This behaviour gets more painful when you try to share the website link and you see an image like the one below.

Image is taken from https://scotch.io/

So, to address this issue, our application has to be rendered on the server side as well. Server Side Rendering — SSR, is a reliable, flexible and an efficient way to ensure all search engines & social networks can access your content. Enter 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 the server to process angular code and templates. It loads our app on the server first, and then drops it to the browser once ready.

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

$ npm install -g @angular/cli
$ ng new angular-server-side-rendering

Install the following dependencies for SSR

$ npm install --save @angular/platform-server @nguniversal/express-engine reflect-metadata

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

First we need to call BrowserModule.withServerTransition method. This method will tell 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

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, let to the CLI create our bundles, run the following command to see if it builds correctly.

/* Build the client bundle and server bundle */
$ ng build --prod && ng build --prod --app 1 --output-hashing=none

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

--

--