27.09.2022
5 min read
Tachometer zeigt eine Geschwindigkeitsskala von 0 bis 260 km/h und eine Kraftstoffanzeige für Diesel bei halb voll.

Angular Server Side Rendering Performance Analysis

  • performance
Short summary:

Angular is a popular frontend framework for single-page web applications. Server Side Rendering offers a way to speed up the initial loading time of the web app and reduce the b

The setup

Info: You can find all code samples of this blog post in our public repository on Github.

A typical Angular application renders pages in the DOM in the browser in response to user actions. Angular has a mechanism called Change detection to track state changes in the application and how the DOM needs to be updated, so the developer doesn't have to. More information on Angular Change detection can be found here.

Angular Universal optimizes web application load times by executing on the server - instead of the browser - generating static application pages that are later bootstrapped on the client side.

A thorough comparison of different rendering approaches is beyond the scope of this post and can be found here: Rendering on the Web.

Let's first kick off a regular Angular application.

A regular Angular app

Initially, we start with a clean ng new angular-ssr CLI command to scaffold the Angular app. This generates a new Angular web application without any optimizations in place. When we run ng serve, the app is served successfully on http://localhost:4200.

To build the production version of the Angular application, we need to execute

ng build -c production

This generates a production build at dist/angular-ssr:

As we are going to compare the Angular production build performance with the Angular SSR performance via Lighthouse audits, we need to deploy the Angular app. For this, we chose the Amazon S3 bucket service - the deployed app can be found here: http://angular-ssr-sample.s3-website.eu-central-1.amazonaws.com

Let's run the Web.dev Measurements:

Wow - amazing first results! This benchmark is quite impressive. All major categories above 90 points. Let's see if we can beat this with Angular SSR.

Angular Universal and Server-side rendering

To enable server-side rendering in our Angular app, we need to perform some basic steps (and some more advanced ones).

  1. ng add @nguniversal/express-engine to add the Angular Universal functionality
  2. npm run dev:ssr to test the Angular Universal app
  3. Decide on the deployment target - we use Vercel

As Angular SSR needs - as the name already implies - some server to execute the rendering, we cannot use plain object-serving solutions such as Amazon S3. We need to switch to a serving solution that supports server-side JavaScript execution.

1. Add a vercel.json file to the project to configure the server environment and prepare for Angular server-side rendering.

Json{
  "version": 2,
  "public": true,
  "name": "test-universal",
  "rewrites": [
    { "source": "/(.*)", "destination": "/api" }
  ],
  "functions": {
    "api/index.js": {
      "includeFiles": "dist/YOUR_PROJECT_NAME/browser/**"
    }
  }
}

2. Adapt the package.json to add new script targets

Json"scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build-dev": "ng build",
    "watch": "ng build --watch --configuration development",
    "test": "ng test",
    "dev:ssr": "ng run angular-ssr:serve-ssr",
    "serve:ssr": "node dist/angular-ssr/server/main.js",
    "build:ssr": "ng build --configuration production && ng run angular-ssr:server",
    "prerender": "ng run angular-ssr:prerender",
    "vercel-build": "npm run build:ssr"
  },

3. Create a new api/index.js file to serve the server-side scripts. This script is quite straightforward:

Javascriptconst server = require('../dist/angular-ssr/server/main');

module.exports = server.app();

Now the setup is ready to be deployed on Vercel - we just connected the Github repository to trigger updates and deploy changes automatically from the repository.

The deployed app can be reached at: https://angular-ssr-sample-b55z.vercel.app

Let's run the Web.dev measurements:

Very interesting! This is slightly worse performance than the production build deployed directly to Amazon S3. We will delve into the details of this in our next post.

Conclusion

While server-side rendering seems to be the holy grail for optimizing apps, it is not always the best solution. When developing Angular apps, the production build already does an amazing job of optimizing the bundle size. So it depends:

  • Are you integrating many third-party npm packages?
  • Is your app serving many different landing pages?

The answers to these questions are crucial for making the right decision regarding web app optimization. Unfortunately, there is no silver bullet for optimizing Angular apps - the best approach depends on the use case.

Feel free to reproduce the measurements right here https://web.dev/measure as the results might vary slightly over time.

What's your experience with Angular app optimization? Feel free to reach out to us!