SlideShare uma empresa Scribd logo
1 de 69
Baixar para ler offline
SSR (Server Side Rendering)
Strategies & Technics
About mySelf
• Experienced FE developer, specialised in B2C applications.
• FE Team Lead @ market.co.uk
• Weekends FE developer @ fashbash.co
Server Side Rendering
Server Side Rendering
What is it?
SSR Will give you the ability
to run and serve your app
from the server
Or in other words…
Pre-Rendering
Angular is SPA
And thats a huge
advantage
But…
There is a cost
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>ServerSideRenderingTalk</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
<app-root></app-root>
</body>
</html>
Angular
Universal
Fast
Loading
SEO
Crawlable Scrapable
Fast loading
"We found that 53% of mobile site visits
are abandoned if pages take longer than
3 second to load…”
• - - prod (AOT, Minification, tree shacking)
• Lazy Loading
• Soon to by - Ivy
• Opportunity for improve?
• Time between html load & bootstrap
Page load Optimisations
What we want to measure?
Time for first
meaningful paint
Time to interactive
Page Load
Page Load
SSR
Regular

load
0 30 60 90 120
index.html load App bootstrap First view
Social
Scrapeable
SEO crawlers
They can’t run
JavaScript
And yet…
Universal
can
be a heavy lift
• Unsupported features:
• window object
• document
• localStorage
• nativeElement changed directly
• And More…
Not everything is PINK
Do I really need
this?
“Do new users discover
your app for the first
time through a link”
- Jeff Whelpley, co-founder of Angular Universal
If you need it,
Let’s do it!
Demo…
ng generate universal --client-project *project-name*
CREATE src/main.server.ts (220 bytes)
CREATE src/app/app.server.module.ts (318 bytes)
CREATE src/tsconfig.server.json (219 bytes)
UPDATE package.json (1374 bytes)
UPDATE angular.json (4107 bytes)
UPDATE src/main.ts (430 bytes)
UPDATE src/app/app.module.ts (965 bytes)
renderModuleFactory(AppServerModuleNgFactory, {
document: index,
url: req.url
})
npm install @nguniversal/express-engine --save
npm install @nguniversal/module-map-ngfactory-
loader --save
"server-build": "ng build --prod && ng run server-side-
rendering-talk:server”
"start:server": "./node_modules/.bin/ts-node ./
server.ts"
package.json
enableProdMode();
const app = express();
const distPath = __dirname + '/dist';
app.engine('html', ngExpressEngine({
bootstrap: AppServerModuleNgFactory,
providers: [provideModuleMap(LAZY_MODULE_MAP)]
}));
app.set('view engine', 'html');
app.set('views', distPath);
app.get('*.*', express.static(distPath));
app.get('*', (req, res) => {
res.render('index', {req});
});
server.ts
enableProdMode();
const app = express();
const distPath = __dirname + '/dist';
app.engine('html', ngExpressEngine({
bootstrap: AppServerModuleNgFactory,
providers: [provideModuleMap(LAZY_MODULE_MAP)]
}));
app.set('view engine', 'html');
app.set('views', distPath);
app.get('*.*', express.static(distPath));
app.get('*', (req, res) => {
res.render('index', {req});
});
server.ts
enableProdMode();
const app = express();
const distPath = __dirname + '/dist';
app.engine('html', ngExpressEngine({
bootstrap: AppServerModuleNgFactory,
providers: [provideModuleMap(LAZY_MODULE_MAP)]
}));
app.set('view engine', 'html');
app.set('views', distPath);
app.get('*.*', express.static(distPath));
app.get('*', (req, res) => {
res.render('index', {req});
});
server.ts
enableProdMode();
const app = express();
const distPath = __dirname + '/dist';
app.engine('html', ngExpressEngine({
bootstrap: AppServerModuleNgFactory,
providers: [provideModuleMap(LAZY_MODULE_MAP)]
}));
app.set('view engine', 'html');
app.set('views', distPath);
app.get('*.*', express.static(distPath));
app.get('*', (req, res) => {
res.render('index', {req});
});
server.ts
enableProdMode();
const app = express();
const distPath = __dirname + '/dist';
app.engine('html', ngExpressEngine({
bootstrap: AppServerModuleNgFactory,
providers: [provideModuleMap(LAZY_MODULE_MAP)]
}));
app.set('view engine', 'html');
app.set('views', distPath);
app.get('*.*', express.static(distPath));
app.get('*', (req, res) => {
res.render('index', {req});
});
server.ts
Control the META
ngOnInit() {
this.paramsSubscription = this.route.data.subscribe((data: any) => {
this.item = data['data'][0];
this.title.setTitle(this.item.description);
this.meta.addTag({
name: 'description',
content: this.item.description
});
});
product-page.component.ts
const twitterTags = [];
twitterTags.push({ name: 'twitter:card', content: 'summary' });
twitterTags.push({ name: 'twitter:site', content: '@EliranEliassy' });
twitterTags.push({ name: 'twitter:title', content: this.item.description });
twitterTags.push({ name: 'twitter:description', content: this.item.description });
twitterTags.push({ name: 'twitter:text:description', content: this.item.description });
twitterTags.push({ name: 'twitter:image', content: this.item.imageUrl });
this.meta.addTags(twitterTags);
product-page.component.ts
const fbTags = [];
fbTags.push({ name: 'og:title', content: this.item.description });
fbTags.push({ name: 'og:image', content: this.item.imageUrl });
fbTags.push({ name: 'og:site_name', content: 'Fake MarketPlace' });
fbTags.push({ name: 'og:description', content: this.item.description });
this.meta.addTags(fbTags);
product-page.component.ts
NOW…Let’s check
the performance
Client Side Rendering
Server Side Rendering
• Time for first meaningful paint: CSR < SSR
• Time to interactive: CSR > SSR
Results
You downloading a lot of text
with your index.html
What can we do?
1. Partially SSR
SsrNoRender Directive
constructor(private viewContainerRef: ViewContainerRef,
private templateRef: TemplateRef<any>,
@Inject(PLATFORM_ID) private platformId) { }
ngOnInit(): void {
if (isPlatformServer(this.platformId)) {
this.viewContainerRef.clear();
} else {
this.viewContainerRef.createEmbeddedView(this.templateRef);
}
}
SsrNoRender Directive
constructor(private viewContainerRef: ViewContainerRef,
private templateRef: TemplateRef<any>,
@Inject(PLATFORM_ID) private platformId) { }
ngOnInit(): void {
if (isPlatformServer(this.platformId)) {
this.viewContainerRef.clear();
} else {
this.viewContainerRef.createEmbeddedView(this.templateRef);
}
}
app.component.html
<app-header></app-header>
<div class="container text-center">
<ng-container *appSsrNoRender>
<router-outlet></router-outlet>
</ng-container>
<div class="loader" *appSsrRender></div>
</div>
2. Angular
Elements
3. Avoid double
XHR requests
Product page resolver
resolve(route: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<any> {
const productId = route.params['id'];
return this.productService.getProductById(productId);
}
Product page resolver
constructor(private productService: ProductService,
@Inject(PLATFORM_ID) private platformId,
private transferState: TransferState) { }
Product page resolver
const productId = route.params['id'];
const key = makeStateKey<any>(productId);
if (this.transferState.hasKey(key)) {
const item = this.transferState.get<any>(key, null);
this.transferState.remove(key);
return of(item);
} else {
return this.productService.getProductById(productId)
.pipe(
tap(item => {
if (isPlatformServer(this.platformId)) {
this.transferState.set(key, item);
}
})
);
}
Product page resolver
const productId = route.params['id'];
const key = makeStateKey<any>(productId);
if (this.transferState.hasKey(key)) {
const item = this.transferState.get<any>(key, null);
this.transferState.remove(key);
return of(item);
} else {
return this.productService.getProductById(productId)
.pipe(
tap(item => {
if (isPlatformServer(this.platformId)) {
this.transferState.set(key, item);
}
})
);
}
Product page resolver
const productId = route.params['id'];
const key = makeStateKey<any>(productId);
if (this.transferState.hasKey(key)) {
const item = this.transferState.get<any>(key, null);
this.transferState.remove(key);
return of(item);
} else {
return this.productService.getProductById(productId)
.pipe(
tap(item => {
if (isPlatformServer(this.platformId)) {
this.transferState.set(key, item);
}
})
);
}
4. Server-Cache
your response
const cache = new Map();
export function ngExpressEngine(setupOptions) {
return function (filePath, options, callback) {
if (!cache.has(filePath)) {
const content = fs.readFileSync(filePath).toString();
cache.set(filePath, content);
}
renderModuleFactory(setupOptions.bootstrap[0], {
document: cache.get(filePath),
url: options.req.url
})
.then(string => {
callback(null, string);
});
};
}
server.ts
const cache = new Map();
export function ngExpressEngine(setupOptions) {
return function (filePath, options, callback) {
if (!cache.has(filePath)) {
const content = fs.readFileSync(filePath).toString();
cache.set(filePath, content);
}
renderModuleFactory(setupOptions.bootstrap[0], {
document: cache.get(filePath),
url: options.req.url
})
.then(string => {
callback(null, string);
});
};
}
server.ts
Did I said
that it can
be a
heavy lift?
Deployment
Run it on the cloud
• Super FAST response time
• Cheaper than servers instances
• Easy to deploy
Thank You
@EliranEliassy eliran.eliassy@gmail.comeliraneliassy

Mais conteúdo relacionado

Mais procurados

Intro to Asynchronous Javascript
Intro to Asynchronous JavascriptIntro to Asynchronous Javascript
Intro to Asynchronous JavascriptGarrett Welson
 
Angular & RXJS: examples and use cases
Angular & RXJS: examples and use casesAngular & RXJS: examples and use cases
Angular & RXJS: examples and use casesFabio Biondi
 
React JS - A quick introduction tutorial
React JS - A quick introduction tutorialReact JS - A quick introduction tutorial
React JS - A quick introduction tutorialMohammed Fazuluddin
 
Angular - Chapter 2 - TypeScript Programming
Angular - Chapter 2 - TypeScript Programming  Angular - Chapter 2 - TypeScript Programming
Angular - Chapter 2 - TypeScript Programming WebStackAcademy
 
Angular data binding
Angular data binding Angular data binding
Angular data binding Sultan Ahmed
 
ASP.NET Core MVC + Web API with Overview
ASP.NET Core MVC + Web API with OverviewASP.NET Core MVC + Web API with Overview
ASP.NET Core MVC + Web API with OverviewShahed Chowdhuri
 
Understanding MicroSERVICE Architecture with Java & Spring Boot
Understanding MicroSERVICE Architecture with Java & Spring BootUnderstanding MicroSERVICE Architecture with Java & Spring Boot
Understanding MicroSERVICE Architecture with Java & Spring BootKashif Ali Siddiqui
 
Introducing type script
Introducing type scriptIntroducing type script
Introducing type scriptRemo Jansen
 
Angular Best Practices To Build Clean and Performant Web Applications
Angular Best Practices To Build Clean and Performant Web ApplicationsAngular Best Practices To Build Clean and Performant Web Applications
Angular Best Practices To Build Clean and Performant Web ApplicationsAlbiorix Technology
 
Understanding react hooks
Understanding react hooksUnderstanding react hooks
Understanding react hooksSamundra khatri
 
Building blocks of Angular
Building blocks of AngularBuilding blocks of Angular
Building blocks of AngularKnoldus Inc.
 
Angular 4 The new Http Client Module
Angular 4 The new Http Client ModuleAngular 4 The new Http Client Module
Angular 4 The new Http Client Modulearjun singh
 
JavaScript Fetch API
JavaScript Fetch APIJavaScript Fetch API
JavaScript Fetch APIXcat Liu
 
Log management system for Microservices
Log management system for MicroservicesLog management system for Microservices
Log management system for MicroservicesVõ Duy Tuấn
 
REST API and CRUD
REST API and CRUDREST API and CRUD
REST API and CRUDPrem Sanil
 

Mais procurados (20)

Intro to Asynchronous Javascript
Intro to Asynchronous JavascriptIntro to Asynchronous Javascript
Intro to Asynchronous Javascript
 
Introduction to GraphQL
Introduction to GraphQLIntroduction to GraphQL
Introduction to GraphQL
 
Angular & RXJS: examples and use cases
Angular & RXJS: examples and use casesAngular & RXJS: examples and use cases
Angular & RXJS: examples and use cases
 
Angular modules in depth
Angular modules in depthAngular modules in depth
Angular modules in depth
 
React JS - A quick introduction tutorial
React JS - A quick introduction tutorialReact JS - A quick introduction tutorial
React JS - A quick introduction tutorial
 
Angular - Chapter 2 - TypeScript Programming
Angular - Chapter 2 - TypeScript Programming  Angular - Chapter 2 - TypeScript Programming
Angular - Chapter 2 - TypeScript Programming
 
Angular data binding
Angular data binding Angular data binding
Angular data binding
 
ASP.NET Core MVC + Web API with Overview
ASP.NET Core MVC + Web API with OverviewASP.NET Core MVC + Web API with Overview
ASP.NET Core MVC + Web API with Overview
 
Understanding MicroSERVICE Architecture with Java & Spring Boot
Understanding MicroSERVICE Architecture with Java & Spring BootUnderstanding MicroSERVICE Architecture with Java & Spring Boot
Understanding MicroSERVICE Architecture with Java & Spring Boot
 
Angularjs PPT
Angularjs PPTAngularjs PPT
Angularjs PPT
 
TypeScript
TypeScriptTypeScript
TypeScript
 
Introducing type script
Introducing type scriptIntroducing type script
Introducing type script
 
Angular Best Practices To Build Clean and Performant Web Applications
Angular Best Practices To Build Clean and Performant Web ApplicationsAngular Best Practices To Build Clean and Performant Web Applications
Angular Best Practices To Build Clean and Performant Web Applications
 
Understanding react hooks
Understanding react hooksUnderstanding react hooks
Understanding react hooks
 
Building blocks of Angular
Building blocks of AngularBuilding blocks of Angular
Building blocks of Angular
 
Angular 4 The new Http Client Module
Angular 4 The new Http Client ModuleAngular 4 The new Http Client Module
Angular 4 The new Http Client Module
 
JavaScript Fetch API
JavaScript Fetch APIJavaScript Fetch API
JavaScript Fetch API
 
Log management system for Microservices
Log management system for MicroservicesLog management system for Microservices
Log management system for Microservices
 
Angular overview
Angular overviewAngular overview
Angular overview
 
REST API and CRUD
REST API and CRUDREST API and CRUD
REST API and CRUD
 

Semelhante a Angular server side rendering - Strategies & Technics

Maciej Treder ''Angular Universal - a medicine for the Angular + SEO/CDN issu...
Maciej Treder ''Angular Universal - a medicine for the Angular + SEO/CDN issu...Maciej Treder ''Angular Universal - a medicine for the Angular + SEO/CDN issu...
Maciej Treder ''Angular Universal - a medicine for the Angular + SEO/CDN issu...OdessaJS Conf
 
Maciej Treder "Server-side rendering with Angular—be faster and more SEO, CDN...
Maciej Treder "Server-side rendering with Angular—be faster and more SEO, CDN...Maciej Treder "Server-side rendering with Angular—be faster and more SEO, CDN...
Maciej Treder "Server-side rendering with Angular—be faster and more SEO, CDN...Fwdays
 
Android app development basics
Android app development basicsAndroid app development basics
Android app development basicsAnton Narusberg
 
Building Single Page Application (SPA) with Symfony2 and AngularJS
Building Single Page Application (SPA) with Symfony2 and AngularJSBuilding Single Page Application (SPA) with Symfony2 and AngularJS
Building Single Page Application (SPA) with Symfony2 and AngularJSAntonio Peric-Mazar
 
Introducing Rendr: Run your Backbone.js apps on the client and server
Introducing Rendr: Run your Backbone.js apps on the client and serverIntroducing Rendr: Run your Backbone.js apps on the client and server
Introducing Rendr: Run your Backbone.js apps on the client and serverSpike Brehm
 
Fragments: Why, How, What For?
Fragments: Why, How, What For?Fragments: Why, How, What For?
Fragments: Why, How, What For?Brenda Cook
 
Mobile App Development: Primi passi con NativeScript e Angular 2
Mobile App Development: Primi passi con NativeScript e Angular 2Mobile App Development: Primi passi con NativeScript e Angular 2
Mobile App Development: Primi passi con NativeScript e Angular 2Filippo Matteo Riggio
 
Heroku pop-behind-the-sense
Heroku pop-behind-the-senseHeroku pop-behind-the-sense
Heroku pop-behind-the-senseBen Lin
 
Building Web Apps with Express
Building Web Apps with ExpressBuilding Web Apps with Express
Building Web Apps with ExpressAaron Stannard
 
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)Igor Bronovskyy
 
AngularJS training - Day 1 - Basics: Why, What and basic features of AngularJS
AngularJS training - Day 1 - Basics: Why, What and basic features of AngularJSAngularJS training - Day 1 - Basics: Why, What and basic features of AngularJS
AngularJS training - Day 1 - Basics: Why, What and basic features of AngularJSmurtazahaveliwala
 
Building a dashboard using AngularJS
Building a dashboard using AngularJSBuilding a dashboard using AngularJS
Building a dashboard using AngularJSRajthilakMCA
 
A gently introduction to AngularJS
A gently introduction to AngularJSA gently introduction to AngularJS
A gently introduction to AngularJSGregor Woiwode
 
Universal JavaScript Web Applications with React - Luciano Mammino - Codemoti...
Universal JavaScript Web Applications with React - Luciano Mammino - Codemoti...Universal JavaScript Web Applications with React - Luciano Mammino - Codemoti...
Universal JavaScript Web Applications with React - Luciano Mammino - Codemoti...Codemotion
 
Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome ...
Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome ...Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome ...
Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome ...Luciano Mammino
 
Rits Brown Bag - Salesforce Lightning
Rits Brown Bag - Salesforce LightningRits Brown Bag - Salesforce Lightning
Rits Brown Bag - Salesforce LightningRight IT Services
 
A Story about AngularJS modularization development
A Story about AngularJS modularization developmentA Story about AngularJS modularization development
A Story about AngularJS modularization developmentJohannes Weber
 

Semelhante a Angular server side rendering - Strategies & Technics (20)

Maciej Treder ''Angular Universal - a medicine for the Angular + SEO/CDN issu...
Maciej Treder ''Angular Universal - a medicine for the Angular + SEO/CDN issu...Maciej Treder ''Angular Universal - a medicine for the Angular + SEO/CDN issu...
Maciej Treder ''Angular Universal - a medicine for the Angular + SEO/CDN issu...
 
Maciej Treder "Server-side rendering with Angular—be faster and more SEO, CDN...
Maciej Treder "Server-side rendering with Angular—be faster and more SEO, CDN...Maciej Treder "Server-side rendering with Angular—be faster and more SEO, CDN...
Maciej Treder "Server-side rendering with Angular—be faster and more SEO, CDN...
 
Android app development basics
Android app development basicsAndroid app development basics
Android app development basics
 
Building Single Page Application (SPA) with Symfony2 and AngularJS
Building Single Page Application (SPA) with Symfony2 and AngularJSBuilding Single Page Application (SPA) with Symfony2 and AngularJS
Building Single Page Application (SPA) with Symfony2 and AngularJS
 
Node.js server-side rendering
Node.js server-side renderingNode.js server-side rendering
Node.js server-side rendering
 
Introducing Rendr: Run your Backbone.js apps on the client and server
Introducing Rendr: Run your Backbone.js apps on the client and serverIntroducing Rendr: Run your Backbone.js apps on the client and server
Introducing Rendr: Run your Backbone.js apps on the client and server
 
Fragments: Why, How, What For?
Fragments: Why, How, What For?Fragments: Why, How, What For?
Fragments: Why, How, What For?
 
Mobile App Development: Primi passi con NativeScript e Angular 2
Mobile App Development: Primi passi con NativeScript e Angular 2Mobile App Development: Primi passi con NativeScript e Angular 2
Mobile App Development: Primi passi con NativeScript e Angular 2
 
Heroku pop-behind-the-sense
Heroku pop-behind-the-senseHeroku pop-behind-the-sense
Heroku pop-behind-the-sense
 
Building Web Apps with Express
Building Web Apps with ExpressBuilding Web Apps with Express
Building Web Apps with Express
 
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
 
AngularJS training - Day 1 - Basics: Why, What and basic features of AngularJS
AngularJS training - Day 1 - Basics: Why, What and basic features of AngularJSAngularJS training - Day 1 - Basics: Why, What and basic features of AngularJS
AngularJS training - Day 1 - Basics: Why, What and basic features of AngularJS
 
Let's react - Meetup
Let's react - MeetupLet's react - Meetup
Let's react - Meetup
 
GHC
GHCGHC
GHC
 
Building a dashboard using AngularJS
Building a dashboard using AngularJSBuilding a dashboard using AngularJS
Building a dashboard using AngularJS
 
A gently introduction to AngularJS
A gently introduction to AngularJSA gently introduction to AngularJS
A gently introduction to AngularJS
 
Universal JavaScript Web Applications with React - Luciano Mammino - Codemoti...
Universal JavaScript Web Applications with React - Luciano Mammino - Codemoti...Universal JavaScript Web Applications with React - Luciano Mammino - Codemoti...
Universal JavaScript Web Applications with React - Luciano Mammino - Codemoti...
 
Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome ...
Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome ...Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome ...
Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome ...
 
Rits Brown Bag - Salesforce Lightning
Rits Brown Bag - Salesforce LightningRits Brown Bag - Salesforce Lightning
Rits Brown Bag - Salesforce Lightning
 
A Story about AngularJS modularization development
A Story about AngularJS modularization developmentA Story about AngularJS modularization development
A Story about AngularJS modularization development
 

Mais de Eliran Eliassy

Angular - Improve Runtime performance 2019
Angular - Improve Runtime performance 2019Angular - Improve Runtime performance 2019
Angular - Improve Runtime performance 2019Eliran Eliassy
 
Angular - injection tokens & Custom libraries
Angular - injection tokens & Custom librariesAngular - injection tokens & Custom libraries
Angular - injection tokens & Custom librariesEliran Eliassy
 
Intro to HTML and CSS basics
Intro to HTML and CSS basicsIntro to HTML and CSS basics
Intro to HTML and CSS basicsEliran Eliassy
 
Angular performance improvments
Angular performance improvmentsAngular performance improvments
Angular performance improvmentsEliran Eliassy
 

Mais de Eliran Eliassy (10)

Angular - Improve Runtime performance 2019
Angular - Improve Runtime performance 2019Angular - Improve Runtime performance 2019
Angular - Improve Runtime performance 2019
 
Between JS and AI
Between JS and AIBetween JS and AI
Between JS and AI
 
Ngrx meta reducers
Ngrx meta reducersNgrx meta reducers
Ngrx meta reducers
 
Angular CDK
Angular CDKAngular CDK
Angular CDK
 
Angular - injection tokens & Custom libraries
Angular - injection tokens & Custom librariesAngular - injection tokens & Custom libraries
Angular - injection tokens & Custom libraries
 
Runtime performance
Runtime performanceRuntime performance
Runtime performance
 
Intro to HTML and CSS basics
Intro to HTML and CSS basicsIntro to HTML and CSS basics
Intro to HTML and CSS basics
 
Angular performance improvments
Angular performance improvmentsAngular performance improvments
Angular performance improvments
 
Angular genericforms2
Angular genericforms2Angular genericforms2
Angular genericforms2
 
Generic forms
Generic formsGeneric forms
Generic forms
 

Último

DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamUiPathCommunity
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MIND CTI
 
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...Zilliz
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoffsammart93
 
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...apidays
 
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...apidays
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfsudhanshuwaghmare1
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDropbox
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherRemote DBA Services
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...DianaGray10
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Victor Rentea
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FMESafe Software
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...Zilliz
 
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...apidays
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesrafiqahmad00786416
 
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfRising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfOrbitshub
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native ApplicationsWSO2
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century educationjfdjdjcjdnsjd
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc
 

Último (20)

DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
 
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor Presentation
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
 
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challenges
 
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfRising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 

Angular server side rendering - Strategies & Technics

  • 1. SSR (Server Side Rendering) Strategies & Technics
  • 2. About mySelf • Experienced FE developer, specialised in B2C applications. • FE Team Lead @ market.co.uk • Weekends FE developer @ fashbash.co
  • 3.
  • 4.
  • 8. SSR Will give you the ability to run and serve your app from the server
  • 9. Or in other words… Pre-Rendering
  • 11. And thats a huge advantage But… There is a cost
  • 12. <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>ServerSideRenderingTalk</title> <base href="/"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="icon" type="image/x-icon" href="favicon.ico"> </head> <body> <app-root></app-root> </body> </html>
  • 15. "We found that 53% of mobile site visits are abandoned if pages take longer than 3 second to load…”
  • 16. • - - prod (AOT, Minification, tree shacking) • Lazy Loading • Soon to by - Ivy • Opportunity for improve? • Time between html load & bootstrap Page load Optimisations
  • 17. What we want to measure? Time for first meaningful paint Time to interactive
  • 19. Page Load SSR Regular
 load 0 30 60 90 120 index.html load App bootstrap First view
  • 21.
  • 22.
  • 23.
  • 25.
  • 28. • Unsupported features: • window object • document • localStorage • nativeElement changed directly • And More… Not everything is PINK
  • 29. Do I really need this?
  • 30. “Do new users discover your app for the first time through a link” - Jeff Whelpley, co-founder of Angular Universal
  • 31. If you need it, Let’s do it! Demo…
  • 32. ng generate universal --client-project *project-name* CREATE src/main.server.ts (220 bytes) CREATE src/app/app.server.module.ts (318 bytes) CREATE src/tsconfig.server.json (219 bytes) UPDATE package.json (1374 bytes) UPDATE angular.json (4107 bytes) UPDATE src/main.ts (430 bytes) UPDATE src/app/app.module.ts (965 bytes)
  • 34. npm install @nguniversal/express-engine --save npm install @nguniversal/module-map-ngfactory- loader --save
  • 35. "server-build": "ng build --prod && ng run server-side- rendering-talk:server” "start:server": "./node_modules/.bin/ts-node ./ server.ts" package.json
  • 36. enableProdMode(); const app = express(); const distPath = __dirname + '/dist'; app.engine('html', ngExpressEngine({ bootstrap: AppServerModuleNgFactory, providers: [provideModuleMap(LAZY_MODULE_MAP)] })); app.set('view engine', 'html'); app.set('views', distPath); app.get('*.*', express.static(distPath)); app.get('*', (req, res) => { res.render('index', {req}); }); server.ts
  • 37. enableProdMode(); const app = express(); const distPath = __dirname + '/dist'; app.engine('html', ngExpressEngine({ bootstrap: AppServerModuleNgFactory, providers: [provideModuleMap(LAZY_MODULE_MAP)] })); app.set('view engine', 'html'); app.set('views', distPath); app.get('*.*', express.static(distPath)); app.get('*', (req, res) => { res.render('index', {req}); }); server.ts
  • 38. enableProdMode(); const app = express(); const distPath = __dirname + '/dist'; app.engine('html', ngExpressEngine({ bootstrap: AppServerModuleNgFactory, providers: [provideModuleMap(LAZY_MODULE_MAP)] })); app.set('view engine', 'html'); app.set('views', distPath); app.get('*.*', express.static(distPath)); app.get('*', (req, res) => { res.render('index', {req}); }); server.ts
  • 39. enableProdMode(); const app = express(); const distPath = __dirname + '/dist'; app.engine('html', ngExpressEngine({ bootstrap: AppServerModuleNgFactory, providers: [provideModuleMap(LAZY_MODULE_MAP)] })); app.set('view engine', 'html'); app.set('views', distPath); app.get('*.*', express.static(distPath)); app.get('*', (req, res) => { res.render('index', {req}); }); server.ts
  • 40. enableProdMode(); const app = express(); const distPath = __dirname + '/dist'; app.engine('html', ngExpressEngine({ bootstrap: AppServerModuleNgFactory, providers: [provideModuleMap(LAZY_MODULE_MAP)] })); app.set('view engine', 'html'); app.set('views', distPath); app.get('*.*', express.static(distPath)); app.get('*', (req, res) => { res.render('index', {req}); }); server.ts
  • 42. ngOnInit() { this.paramsSubscription = this.route.data.subscribe((data: any) => { this.item = data['data'][0]; this.title.setTitle(this.item.description); this.meta.addTag({ name: 'description', content: this.item.description }); }); product-page.component.ts
  • 43. const twitterTags = []; twitterTags.push({ name: 'twitter:card', content: 'summary' }); twitterTags.push({ name: 'twitter:site', content: '@EliranEliassy' }); twitterTags.push({ name: 'twitter:title', content: this.item.description }); twitterTags.push({ name: 'twitter:description', content: this.item.description }); twitterTags.push({ name: 'twitter:text:description', content: this.item.description }); twitterTags.push({ name: 'twitter:image', content: this.item.imageUrl }); this.meta.addTags(twitterTags); product-page.component.ts
  • 44. const fbTags = []; fbTags.push({ name: 'og:title', content: this.item.description }); fbTags.push({ name: 'og:image', content: this.item.imageUrl }); fbTags.push({ name: 'og:site_name', content: 'Fake MarketPlace' }); fbTags.push({ name: 'og:description', content: this.item.description }); this.meta.addTags(fbTags); product-page.component.ts
  • 48. • Time for first meaningful paint: CSR < SSR • Time to interactive: CSR > SSR Results You downloading a lot of text with your index.html
  • 49.
  • 50. What can we do?
  • 52. SsrNoRender Directive constructor(private viewContainerRef: ViewContainerRef, private templateRef: TemplateRef<any>, @Inject(PLATFORM_ID) private platformId) { } ngOnInit(): void { if (isPlatformServer(this.platformId)) { this.viewContainerRef.clear(); } else { this.viewContainerRef.createEmbeddedView(this.templateRef); } }
  • 53. SsrNoRender Directive constructor(private viewContainerRef: ViewContainerRef, private templateRef: TemplateRef<any>, @Inject(PLATFORM_ID) private platformId) { } ngOnInit(): void { if (isPlatformServer(this.platformId)) { this.viewContainerRef.clear(); } else { this.viewContainerRef.createEmbeddedView(this.templateRef); } }
  • 54. app.component.html <app-header></app-header> <div class="container text-center"> <ng-container *appSsrNoRender> <router-outlet></router-outlet> </ng-container> <div class="loader" *appSsrRender></div> </div>
  • 57. Product page resolver resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any> { const productId = route.params['id']; return this.productService.getProductById(productId); }
  • 58. Product page resolver constructor(private productService: ProductService, @Inject(PLATFORM_ID) private platformId, private transferState: TransferState) { }
  • 59. Product page resolver const productId = route.params['id']; const key = makeStateKey<any>(productId); if (this.transferState.hasKey(key)) { const item = this.transferState.get<any>(key, null); this.transferState.remove(key); return of(item); } else { return this.productService.getProductById(productId) .pipe( tap(item => { if (isPlatformServer(this.platformId)) { this.transferState.set(key, item); } }) ); }
  • 60. Product page resolver const productId = route.params['id']; const key = makeStateKey<any>(productId); if (this.transferState.hasKey(key)) { const item = this.transferState.get<any>(key, null); this.transferState.remove(key); return of(item); } else { return this.productService.getProductById(productId) .pipe( tap(item => { if (isPlatformServer(this.platformId)) { this.transferState.set(key, item); } }) ); }
  • 61. Product page resolver const productId = route.params['id']; const key = makeStateKey<any>(productId); if (this.transferState.hasKey(key)) { const item = this.transferState.get<any>(key, null); this.transferState.remove(key); return of(item); } else { return this.productService.getProductById(productId) .pipe( tap(item => { if (isPlatformServer(this.platformId)) { this.transferState.set(key, item); } }) ); }
  • 63. const cache = new Map(); export function ngExpressEngine(setupOptions) { return function (filePath, options, callback) { if (!cache.has(filePath)) { const content = fs.readFileSync(filePath).toString(); cache.set(filePath, content); } renderModuleFactory(setupOptions.bootstrap[0], { document: cache.get(filePath), url: options.req.url }) .then(string => { callback(null, string); }); }; } server.ts
  • 64. const cache = new Map(); export function ngExpressEngine(setupOptions) { return function (filePath, options, callback) { if (!cache.has(filePath)) { const content = fs.readFileSync(filePath).toString(); cache.set(filePath, content); } renderModuleFactory(setupOptions.bootstrap[0], { document: cache.get(filePath), url: options.req.url }) .then(string => { callback(null, string); }); }; } server.ts
  • 65. Did I said that it can be a heavy lift?
  • 66.
  • 68. Run it on the cloud • Super FAST response time • Cheaper than servers instances • Easy to deploy