ANGUL R OUTSIDE THE BROWSER
ANGULAR FOR
A BETTER TITLE
THE HEADLESS WEB*
INTRODUCING
Wassim Chegham
Developer Advocate
@manekinekko
SOCIAL LINK
PREVIEWING
SERVER
RESPONSE
ASSET DOWNLOADS
CLIENT INIT
CLIENT DATA
PAINTING
0"
3" ~ 20"
THE WEB APP GAP
SERVER
RESPONSE
ASSET DOWNLOADS
CLIENT INIT
CLIENT DATA
PAINTING
SERVER RENDERED PAGE
CLIENT TAKES OVER
USER VIEWS THE PAGE
APPLICATION LAYER
VIEW COMPILER LAYER
RENDERING LAYER
BROWSER
WEB WORKER...
SERVER (NODE)
RECORD EVENTS
ASSET DOWNLOADS
CLIENT INIT
CLIENT DATA
PAINTING
SERVER
CLIENT
REPLAY EVENTS
SERVER
RENDERING
PREBOOT.JS
PREBOOT.JS IS RECORDING EVENTS...
(app.component.ts)
server.ts
browser.ts
server
.module.ts
browser
.module.ts
Application layer
index.html
import { Component } from '@angular/core';
import { Meta, Title } from "@angular/platform-browser";
@Component({
selector: 'app-home',
template: `<h3>Home View</h3>`
})
export class AppComponent {
constructor(meta: Meta, title: Title) {
title.setTitle('Current Title Page');
meta.addTags([
{name: 'author', content: 'Wassim Chegham'},
{name: 'keywords',
content: 'angular,universal,iot,omega2+'},
{name: 'description',
content: 'Angular Universal running on Omega2+'}
]);
}
}
app.component.ts
@NgModule({
imports: [
BrowserModule.withServerTransition({appid: 'universal-app'}),
AppCommonModule,
],
providers: [
{provide: AppService, useClass: ClientAppService},
],
declarations: [AppComponent],
bootstrap: [AppComponent],
})
export class AppBrowserModule {}
browser.module.ts
import { platformBrowser } from '@angular/platform-browser';
import {
AppModule
} from './app/browser.module';
import {
AppModuleNgFactory
} from './ngfactory/browser.module.ngfactory';
platformBrowser().bootstrapModuleFactory(AppModuleNgFactory);
browser.ts
@NgModule({
imports: [
AppBrowserModule,
ServerModule,
],
providers: [
{provide: AppService, useClass: ServerAppService},
],
declarations: [AppComponent],
bootstrap: [AppComponent],
})
export class AppServerModule {}
server.module.ts
import {
AppServerModuleNgFactory
} from '../src.ngfactory/src/app/server.module.ngfactory';
import * as express from 'express';
import { ngExpressEngine } from './app/core/express-engine';
const app = express();
app.engine('html', ngExpressEngine({
baseUrl: 'http://localhost:4200',
bootstrap: [AppServerModuleNgFactory]
}));
app.set('view engine', 'html');
app.get('/', (req, res) => { res.render('index', {req}); });
app.listen(8000,() => console.log('listening...') );
server.ts
const fs = require('fs');
const path = require('path');
import {renderModuleFactory} from '@angular/platform-server';
const templateCache = new Map();
export function ngExpressEngine(setupOptions){
return async function(filePath, options, callback){
if(!templateCache.has(filePath)){
let file = fs.readFileSync(filePath);
templateCache.set(filePath, file.toString());
}
const html = await renderModuleFactory(setupOptions.bootstrap[0], {
document: templateCache.get(filePath),
url: options.req.url
});
callback(null, html);
}
}
express-engine.ts
ONE
MORE
THING
DO NOT EVER NEVER TOUCH
THE DOM
PLEASE
import {Directive, ElementRef, Renderer} from '@angular/core';
@Directive({
selector: '[x-large]'
})
export class XLarge {
constructor(element: ElementRef, renderer: Renderer) {
renderer.setElementStyle(
element.nativeElement, 'fontSize', 'x-large'
);
}
}
RENDERER
USE ANGULAR'S
>4s
~500ms
NODE.js STARTER
CLI ADDON
COMING SOON
# preview CLI
$ npm i universal-cli
# add server-side support
# and SSR on the fly
$ ng new awesome-app --universal
# generate static site
$ ng new awesome-app --universal-prerender
# generate a static version
$ ng build
# generate static docs
$ ng docs
JAVA
PHP
GO
.NET
BETTER
INTEGRATION
WITH ANGULAR
HTTP•TESTING•ZONES•SEMVER...
WE LOVE
CONTRIBUTIONS
click here
TH NK
@manekinekko