1. What is SSR in Angular?
SSR
(Server-Side Rendering) in Angular is the process where Angular
renders your application on the server
instead of the browser. This allows the HTML content to be sent to the client
fully rendered.
Normally, Angular apps are SPA (Single Page Applications):
·
Browser downloads JS bundle → Angular bootstraps
→ Renders the page.
·
Problem: Initial page load is slow; SEO is poor
because crawlers don’t see fully rendered content.
SSR
solves this:
·
Server pre-renders HTML → Sends to browser →
Browser takes over (hydration).
·
Uses Angular
Universal (official Angular tool for SSR).
2. Uses / Benefits of SSR
1.
Improved
SEO
o Search
engines see fully rendered HTML instead of empty index.html
.
2.
Faster
First Paint / Initial Load
o User
sees content faster; especially good for slow networks.
3.
Social
Media Previews
o Open
Graph tags, meta tags render correctly.
4.
Better
Performance Metrics
o Time-to-first-byte
(TTFB) is faster.
3. How to Achieve SSR in
Angular
Angular provides Angular Universal to
implement SSR.
Steps Overview
1.
Add Angular Universal to your Angular app.
2.
Configure server module.
3.
Build and run the app with SSR.
4.
Optional: Deploy to server (Node.js, Azure, Firebase,
etc.)
4. Step-by-Step
Implementation
Step 1: Create Angular App
ng new angular-ssr-app --routing --style=scss
cd angular-ssr-app
Step 2: Add Angular
Universal
ng add @nguniversal/express-engine
This will:
·
Install SSR packages (@nguniversal/express-engine
)
·
Create:
o server.ts
→ Node/Express server for SSR
o src/app/app.server.module.ts
→ Server module
o Update
angular.json
with SSR build configurations
Step 3: Understand the Files
Added
1.
app.server.module.ts
import {
NgModule }
from
'@angular/core';
import {
ServerModule }
from
'@angular/platform-server';
import {
AppModule }
from
'./app.module';
import {
AppComponent }
from
'./app.component';
@NgModule({
imports: [
AppModule,
ServerModule,
],
bootstrap: [
AppComponent],
})
export
class
AppServerModule {}
2.
server.ts
import
'zone.js/node';
import { ngExpressEngine }
from
'@nguniversal/express-engine';
import *
as express
from
'express';
import { join }
from
'path';
import {
AppServerModule }
from
'./src/main.server';
import {
APP_BASE_HREF }
from
'@angular/common';
import { existsSync }
from
'fs';
const app =
express();
const distFolder =
join(process.
cwd(),
'dist/angular-ssr-app/browser');
const indexHtml =
existsSync(
join(distFolder,
'index.original.html')) ?
'index.original.html' :
'index';
app.
engine(
'html',
ngExpressEngine({
bootstrap:
AppServerModule,
}));
app.
set(
'view engine',
'html');
app.
set(
'views', distFolder);
app.
get(
'*.*', express.
static(distFolder));
app.
get(
'*',
(req, res) => {
res.
render(indexHtml, { req,
providers: [{
provide:
APP_BASE_HREF,
useValue: req.
baseUrl }] });
});
const port = process.
env.
PORT ||
4000;
app.
listen(port,
() => {
console.
log(
`Node server listening on http://localhost:${port}`);
});
Step 4: Update Angular
Routing
Ensure your routes are SSR compatible:
const
routes:
Routes = [
{
path:
'',
component:
HomeComponent },
{
path:
'about',
component:
AboutComponent }
];
·
Avoid browser-only
APIs (like window
, document
) in
components without guards.
·
Use Angular Platform checks:
import { isPlatformBrowser }
from
'@angular/common';
import {
PLATFORM_ID,
Inject }
from
'@angular/core';
constructor(
@Inject(PLATFORM_ID)
private platformId:
Object) {}
ngOnInit() {
if (
isPlatformBrowser(
this.
platformId)) {
// browser-only code here
}
}
Step 5: Build SSR App
1.
Build browser app:
ng build
2.
Build server app:
ng run angular-ssr-app:server
Step 6: Run SSR Server
node dist/angular-ssr-app/server/main.js
·
Open in browser: http://localhost:4000
·
View page source → You will see fully rendered HTML (SSR
working!).
Step 7: Deploy SSR App
·
Node.js server needed.
·
Can deploy on:
o Heroku
o Firebase Hosting + Cloud Functions
5. Real-Time Example
Suppose we have Angular blog app:
·
Pages:
o Home
→ List of articles (SSR helps SEO)
o Article
→ Full content of a blog
·
Use SSR for articles → Search engines
can index the content.
·
Without SSR → bots see empty HTML until JS loads
→ bad for SEO.
6. SEO Optimization in
Angular SSR
·
Use @angular/platform-browser
Title & Meta:
import {
Meta,
Title }
from
'@angular/platform-browser';
constructor(
private title: Title,
private meta: Meta) {}
ngOnInit() {
this.
title.
setTitle(
'Angular SSR Blog Home');
this.
meta.
addTags([
{
name:
'description',
content:
'A blog app using Angular SSR' },
{
name:
'keywords',
content:
'Angular, SSR, SEO' },
]);
}
·
These meta tags render on server → improve SEO.
7. Important Notes / Best
Practices
1.
Avoid browser-only code directly in components.
2.
Use Lazy
loading with SSR for large apps.
3.
Use Angular
TransferState to pass data from server → client to reduce API
calls.
4.
Monitor performance: SSR improves TTFB, but server CPU
usage is higher.
✅ Summary
·
SSR
= Angular app renders on server → faster load & SEO.
·
Angular
Universal = Angular tool for SSR.
·
Steps:
1.
Add Angular Universal
2.
Configure server.ts
& app.server.module.ts
3.
Update routes & avoid browser-only code
4.
Build & run SSR app
5.
Deploy on Node.js compatible server
·
Real-world use: Blogs, E-commerce, News apps for
SEO & faster load.
1. Setup Angular + SSR
Create project & add Angular Universal
(SSR):
ng new angular-ssr-blog --routing --style=scss
cd angular-ssr-blog
ng add @nguniversal/express-engine
2. Create Blog Components
Generate Home
and Article pages:
ng g c pages/home
ng g c pages/article
Update app-routing.module.ts
:
import {
NgModule }
from
'@angular/core';
import {
RouterModule,
Routes }
from
'@angular/router';
import {
HomeComponent }
from
'./pages/home/home.component';
import {
ArticleComponent }
from
'./pages/article/article.component';
const
routes:
Routes = [
{
path:
'',
component:
HomeComponent },
{
path:
'article/:id',
component:
ArticleComponent },
];
@NgModule({
imports: [
RouterModule.
forRoot(routes, {
initialNavigation:
'enabledBlocking' })],
exports: [
RouterModule],
})
export
class
AppRoutingModule {}
3. Home Component (Blog
List)
home.component.ts
:
import {
Component,
OnInit }
from
'@angular/core';
import {
Title,
Meta }
from
'@angular/platform-browser';
@Component({
selector:
'app-home',
templateUrl:
'./home.component.html',
})
export
class
HomeComponent
implements
OnInit {
articles = [
{
id:
1,
title:
'Angular SSR Complete Guide',
summary:
'Learn Angular Universal step by step.' },
{
id:
2,
title:
'SEO in Angular',
summary:
'How to optimize Angular apps for SEO with SSR.' },
];
constructor(
private title: Title,
private meta: Meta) {}
ngOnInit():
void {
this.
title.
setTitle(
'Angular SSR Blog - Home');
this.
meta.
addTags([
{
name:
'description',
content:
'Learn Angular SSR (Server-Side Rendering) with real examples.' },
{
name:
'keywords',
content:
'Angular SSR, Angular Universal, SEO, Server Side Rendering, Angular Blog Example' },
]);
}
}
home.component.html
:
<h1>Angular SSR Blog
</h1>
<ul>
<li *
ngFor=
"let article of articles">
<a [
routerLink]=
"['/article', article.id]">{{ article.title }}
</a>
<p>{{ article.summary }}
</p>
</li>
</ul>
4. Article Component (SEO
per Page)
article.component.ts
:
import {
Component,
OnInit }
from
'@angular/core';
import {
ActivatedRoute }
from
'@angular/router';
import {
Title,
Meta }
from
'@angular/platform-browser';
@Component({
selector:
'app-article',
templateUrl:
'./article.component.html',
})
export
class
ArticleComponent
implements
OnInit {
articleId!:
number;
article:
any;
articles = {
1: {
title:
'Angular SSR Complete Guide',
content:
'This article explains Angular Universal step-by-step with configuration and code.',
keywords:
'Angular SSR, Angular Universal, SSR Tutorial, Angular SEO'
},
2: {
title:
'SEO in Angular',
content:
'In this article, you will learn how to optimize Angular applications for SEO using SSR.',
keywords:
'Angular SEO, SSR SEO, Angular Meta Tags, Angular Universal SEO'
}
};
constructor(
private route: ActivatedRoute,
private title: Title,
private meta: Meta
) {}
ngOnInit():
void {
this.
articleId = +
this.
route.
snapshot.
paramMap.
get(
'id')!;
this.
article =
this.
articles[
this.
articleId];
// SEO tags per article
this.
title.
setTitle(
this.
article.
title);
this.
meta.
updateTag({
name:
'description',
content:
this.
article.
content.
slice(
0,
150) });
this.
meta.
updateTag({
name:
'keywords',
content:
this.
article.
keywords });
}
}
article.component.html
:
<h2>{{ article.title }}
</h2>
<p>{{ article.content }}
</p>
<a
routerLink=
"/">
⬅ Back to Home
</a>
5. Run SSR Build
npm run build:ssr && npm run serve:ssr
Visit:
👉 http://localhost:4000
·
View Page
Source → You’ll see pre-rendered
HTML with meta tags (SEO ready ✅).
6. Example SEO Tags
Generated
For Home Page:
<title>Angular SSR Blog - Home
</title>
<meta
name=
"description"
content=
"Learn Angular SSR (Server-Side Rendering) with real examples.">
<meta
name=
"keywords"
content=
"Angular SSR, Angular Universal, SEO, Server Side Rendering, Angular Blog Example">
For Article 1:
<title>Angular SSR Complete Guide
</title>
<meta
name=
"description"
content=
"This article explains Angular Universal step-by-step with configuration and code.">
<meta
name=
"keywords"
content=
"Angular SSR, Angular Universal, SSR Tutorial, Angular SEO">
7. Deployment Options
·
Node.js
Server → Upload to VPS/Heroku/Azure App Service.
·
Firebase
Hosting + Cloud Functions → Good for serverless SSR.
·
NGINX +
Node.js → Classic approach.