Angular Server Side Rendering

Server-side rendering (SSR) is a technique used to render a client-side JavaScript framework on the server, instead of in the browser. This can be useful for a number of reasons, such as improving the performance of your application for users with slower devices or internet connections, or making your application more search engine friendly.

In Angular, server-side rendering can be achieved using the Angular Universal library. Angular Universal allows you to run your Angular application on the server, generating static application pages that can be sent to the client.

Here's a high-level overview of the process of server-side rendering an Angular application:

  1. The user sends a request to the server for a specific page in the application.

  2. The server receives the request and sends it to the Angular application.

  3. The Angular application generates the requested page, including the HTML, CSS, and JavaScript needed to render the page in the browser.

  4. The server sends the generated page back to the client.

  5. The client's browser receives the page and renders it for the user.

One important thing to note is that server-side rendering requires some additional setup and configuration compared to a traditional client-side Angular application. You'll need to set up a server to host your application, and you'll need to configure the server to handle requests from the client and pass them to the Angular application for rendering. You'll also need to set up your Angular application to work with the server-side rendering process, including setting up the necessary dependencies and libraries.

Overall, server-side rendering can be a useful tool for improving the performance and SEO of your Angular application, but it does require some additional work to set up and maintain.

To get started with server-side rendering in Angular, you'll need to install the Angular Universal library and set up your application to use it. Here are the steps to do this:

  1. Install the Angular Universal library by running the following command in your terminal:
npm install @nguniversal/express-engine @nguniversal/module-map-ngfactory-loader --save 
  1. Create a server.ts file in the root of your project, which will be used to start the server and render your application. In this file, you'll need to import the necessary dependencies and set up the server to handle requests from the client. Here's an example of what your server.ts file might look like:
import 'zone.js/dist/zone-node'; 
import 'reflect-metadata'; 
import { enableProdMode } from '@angular/core'; 
import { ngExpressEngine } from '@nguniversal/express-engine'; 
import { provideModuleMap } from '@nguniversal/module-map-ngfactory-loader'; 
import * as express from 'express'; 
import { join } from 'path'; 

// Enable production mode unless running locally 
if (process.env.NODE_ENV === 'production') { 
	enableProdMode(); 
} 

// Express server 
const app = express(); 
const PORT = process.env.PORT || 4000; 
const DIST_FOLDER = join(process.cwd(), 'dist/browser'); 

// * NOTE :: leave this as require() since this file is built Dynamically from webpack 
const { AppServerModuleNgFactory, LAZY_MODULE_MAP } = require('./dist/server/main'); 

// Our Universal express-engine (found @ https://github.com/angular/universal/tree/master/modules/express-engine) 

app.engine('html', ngExpressEngine({ 
	bootstrap: AppServerModuleNgFactory, 
	providers: [ provideModuleMap(LAZY_MODULE_MAP) ] 
})); 
	
app.set('view engine', 'html'); 
app.set('views', DIST_FOLDER); 

// Example Express Rest API endpoints // 
app.get('/api/**', (req, res) => { }); 

// Serve static files from /browser 
app.get('*.*', express.static(DIST_FOLDER, { maxAge: '1y' })); 

// All regular routes use the Universal engine 
app.get('*', (req, res) => { res.render('index', { req }); }); 

// Start up the Node server 
app.listen(PORT, () => { 
console.log(`Node Express server listening on http://localhost:${PORT}`); }); 
  1. In your Angular app's main module (usually app.module.ts), import the ServerModule from @nguniversal/express-engine and add it to the imports array. This will configure your application to use server-side rendering.
  2. In your app's main component (usually app.component.ts), you'll need to make some changes to support server-side rendering. Specifically, you'll need to wrap the contents of the component's template in an additional element with an attribute of *ngIf="isBrowser". This will ensure that the content is only rendered on the client, and not on the server.
  3. Here's an example of what your main component's template might look like:

    <div *ngIf="isBrowser"> <!-- Your component's template content goes here --> </div> 
  4. In your app.component.ts file, you'll need to add a property called isBrowser, which will be used to determine whether the component is being rendered on the server or the client. You can do this by importing the PLATFORM_ID and Inject decorators from Angular and using them to inject the platform ID into the component. You can then use the isPlatformBrowser function from the @angular/common package to check whether the component is being rendered on the browser or on the server. Here's an example of what your app.component.ts file might look like:
  5. import { Component, Inject, PLATFORM_ID } from '@angular/core'; 
    import { isPlatformBrowser } from '@angular/common'; 
    
    @Component({ 
    	selector: 'app-root', 
    	templateUrl: './app.component.html', 
    	styleUrls: ['./app.component.css'] 
    }) 
    
    export class AppComponent { 
    	isBrowser: boolean; 
    	constructor(@Inject(PLATFORM_ID) private platformId: Object) { 
    		this.isBrowser = isPlatformBrowser(platformId); 
    	} 
    } 
  6. Finally, you'll need to update your build and deploy scripts to support server-side rendering. In your package.json file, you'll need to add a script to build the server-side version of your application, as well as a script to start the server. Here's an example of what your package.json scripts section might look like:
  7. "scripts": { 
    		"build:ssr": "ng build --prod && ng run my-app:server:production", 
    		"serve:ssr": "node dist/server", 
    		"build:client-and-server-bundles": "ng build --prod && ng run my-app:server:production", 
    		"build:prod": "npm run build:client-and-server-bundles && ng run my-app:server:production", 
    		"serve:prod": "node dist/server", 
    	"start": "ng serve" 
    }, 

    With these changes in place, you should now be able to build and run your Angular application with server-side rendering enabled. To build the server-side version of your application, you can use the following command:

    npm run build:ssr 

    And to start the server, you can use the following command:

    npm run serve:ssr