Angular SSR - An intro to Angular Universal

Introduction to Angular Universal

Angular Universal is a technology which helps to pre-render our application for better performance, better search engine optimization(SEO), etc. It will run the application on the server like Node.js. Angular Universal will render the application on the server Ahead Of Time(AOT). It will render the static pages at first so that we have something to show to the user immediately. In our client-side applications, we will first bring the data and then HTML is build to show on the client-side. Sometimes there is a subsequent delay in that or UI presentation is done at the last moment. So Angular Universal allows us to pre-render HTML and CSS during build time.

How it works?

When we build an application using Angular Universal, Angular will pre-render initial static HTML and CSS for better user experience. This pre-render content will be shown initially. Afterward, with this server-rendered HTML and CSS content, we will provide the client-side application to our browser. After the server pre-rendered content, our normal client application will run as usual. Using Angular SSR technique, we will have some content to show to the user on the fly. It serves a better user experience with no time delay, better performance, etc. After the server-rendered static code, the client application will be fully interactive with the user. 

Making a Universal App

Our Angular CLI will keep the compiled bundle of our Universal application. The server will compile and provide the static HTML pages based on user requests and interactions. We can create a universal application using the following CLI command:
ng add @nguniversal/express-engine --clientProject {{ project name }}

The above command will create the following additional server configurations files as compared to the normal application. 
main.server.ts               * bootstrapper for server app
app.server.module.ts         * server-side application module
server.ts                    * express web server
tsconfig.server.json         * TypeScript server configuration
webpack.server.config.js     * webpack server configuration

  • main.server.ts - This file will export the AppServerModule which will act as the starting point of our Universal App. It seems like the entry point for the server module.
  • app.server.module.ts - This acts as the root module now for the server application. It will import the AppModule and ServerModule from @angular/platform-server. It also bootstraps AppComponent as AppModule.
  • app.module.ts - We will remove bootstrap property so that our application will no longer get bootstrapped. App module will not bootstrap our app. We will modify and use the static method  BrowserModule.withServerTransition({ appId: ‘name of app’ }). This function will tell Angular that it is a server-rendered application.
  • server.ts - This is the express node server. This server will render HTML on the server. 
  • tsconfig.server.json -  Angular will know the entry module for the application from this file. This file will have the typescript configuration regarding the server module.
  • webpack.server.config.js - This is the webpack configuration for bundling the server.
  • package.json - We will get new scripts and dependencies. 

Starting the Universal App

To start rendering enter the following command:
npm run build:ssr && npm run serve:ssr

Now our universal app will start rendering in the browser at http://localhost:4000. We can change the configuration of the port also. Now we will see that our application will load faster than the normal Angular application. The first page loads faster with Universal.

The difference of source code with Universal

If we open and check the source code of our universal application, we will see that in the <body> tag there are all normal HTML tags. These plain HTML can be understood by the web crawler easily and hence our SEO improves. But if we see the source code of our normal Angular application. We will see <app-root> tag in the <body> tag.

Notes for Universal App

Our universal application will initial run on the server, not on the browser. So the following things should be taken care of:
  • The routerLinks will work correctly. We can navigate from one page to another using routerLinks.
  • The event handling will not work. All the browser event handling such as click, hover will not work as the application will not respond to browser-related events.
  • The user can't perform any add, edit or delete functionality.
  • The search functionality also stops working in the app.
  • We can't use browser objects such as document, window, and location. Instead, we can use Document, Location imported from the Angular.
  • We have to put some code specifically for server or browser. For this, we can use isPlatformBrowser and isPlatformServer functions from @angular/common package. 
  • Avoid the use of setTimeout() function in our code.
  • The URL for server requests should be absolute.