Angular SSR: How to Boost SEO and Performance in Your App

Date: March 27, 2022


Introduction

Single Page Applications (SPAs) like those built with Angular are powerful and dynamic, but they come with SEO and initial load performance challenges because content is rendered client-side. Angular Server-Side Rendering (SSR) solves these issues by rendering your Angular app on the server, delivering fully rendered HTML to the browser.

In this tutorial, we’ll cover the basics of Angular Universal (the official SSR solution), walk through pre-rendering your app, and show how to deploy SSR using Express.js.


Why Use Angular SSR?

  • Improved SEO: Search engines get fully rendered HTML, improving crawlability.
  • Faster Time to First Paint: Users see meaningful content faster, improving user experience.
  • Better Social Sharing: Meta tags and previews work properly because rendered HTML is available.

Setting Up Angular Universal

Angular Universal enables SSR by running your Angular app on the server using Node.js.

Step 1: Add Angular Universal to Your Project

Run the Angular CLI schematic to add Universal:

ng add @nguniversal/express-engine

This command will:

  • Add server-side rendering support.
  • Create server files (server.ts) using Express.
  • Update your Angular build configuration.

Step 2: Build and Serve the SSR App Locally

Build both browser and server apps:

npm run build:ssr

Run the Express server that serves your SSR app:

npm run serve:ssr

Open http://localhost:4000 in your browser. You should see your app rendered from the server.


Pre-rendering Your Angular App

If your app mostly serves static pages (like marketing sites), pre-rendering can generate static HTML at build time.

Add a pre-render target in your angular.json:

"prerender": {
  "builder": "@nguniversal/builders:prerender",
  "options": {
    "browserTarget": "your-app:build:production",
    "serverTarget": "your-app:server:production",
    "routes": ["/", "/about", "/contact"]
  }
}

Run pre-render:

ng run your-app:prerender

This generates static HTML files for the specified routes.


Handling Dynamic Data with SSR

Angular Universal can fetch data on the server before rendering. Use Angular’s TransferState to avoid double HTTP calls on client:

import { TransferState, makeStateKey } from '@angular/platform-browser';

const DATA_KEY = makeStateKey<any>('my-data');

@Injectable()
export class DataService {
  constructor(private http: HttpClient, private state: TransferState) {}

  getData() {
    const savedData = this.state.get(DATA_KEY, null);
    if (savedData) {
      return of(savedData);
    } else {
      return this.http.get('/api/data').pipe(
        tap(data => this.state.set(DATA_KEY, data))
      );
    }
  }
}

Deploying SSR with Express.js

Your server.ts (created by Angular Universal schematic) is an Express server rendering Angular.

To deploy:

  1. Build the SSR bundle:
   npm run build:ssr
  1. Run the server:
   node dist/your-app/server/main.js
  1. Optionally deploy to cloud services like AWS, Azure, or Vercel that support Node.js servers.

Conclusion

Angular SSR with Angular Universal significantly improves SEO and user experience by delivering fully rendered pages from the server. You can combine SSR with pre-rendering depending on your app’s needs and deploy easily using the built-in Express server.

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *