Skip to content
Snippets Groups Projects
Commit 3adbfbd2 authored by Dimitri DI GUSTO's avatar Dimitri DI GUSTO
Browse files

Init SSR engine

parent ef9c5b3e
Branches
No related tags found
No related merge requests found
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
"builder": "@angular-devkit/build-angular:browser", "builder": "@angular-devkit/build-angular:browser",
"options": { "options": {
"aot": true, "aot": true,
"outputPath": "dist", "outputPath": "dist/webapp/browser",
"index": "src/index.html", "index": "src/index.html",
"main": "src/main.ts", "main": "src/main.ts",
"tsConfig": "src/tsconfig.app.json", "tsConfig": "src/tsconfig.app.json",
...@@ -237,6 +237,46 @@ ...@@ -237,6 +237,46 @@
"**/node_modules/**" "**/node_modules/**"
] ]
} }
},
"server": {
"builder": "@angular-devkit/build-angular:server",
"options": {
"outputPath": "dist/webapp/server",
"main": "server.ts",
"tsConfig": "src/tsconfig.server.json"
},
"configurations": {
"production": {
"sourceMap": false,
"optimization": true
}
}
},
"serve-ssr": {
"builder": "@nguniversal/builders:ssr-dev-server",
"options": {
"browserTarget": "webapp:build",
"serverTarget": "webapp:server"
},
"configurations": {
"production": {
"browserTarget": "webapp:build:production",
"serverTarget": "webapp:server:production"
}
}
},
"prerender": {
"builder": "@nguniversal/builders:prerender",
"options": {
"browserTarget": "webapp:build:production",
"serverTarget": "webapp:server:production",
"routes": [
"/"
]
},
"configurations": {
"production": {}
}
} }
} }
}, },
......
This diff is collapsed.
...@@ -17,7 +17,11 @@ ...@@ -17,7 +17,11 @@
"lint": "ng lint", "lint": "ng lint",
"e2e": "ng e2e", "e2e": "ng e2e",
"postinstall": "node patch.js", "postinstall": "node patch.js",
"bundle-report": "webpack-bundle-analyzer dist/stats.json" "bundle-report": "webpack-bundle-analyzer dist/stats.json",
"dev:ssr": "ng run webapp:serve-ssr",
"serve:ssr": "node dist/webapp/server/main.js",
"build:ssr": "ng build --configuration=production-fr && ng run webapp:server:production",
"prerender": "ng run webapp:prerender"
}, },
"private": true, "private": true,
"dependencies": { "dependencies": {
...@@ -30,8 +34,10 @@ ...@@ -30,8 +34,10 @@
"@angular/localize": "~9.1.12", "@angular/localize": "~9.1.12",
"@angular/platform-browser": "9.1.12", "@angular/platform-browser": "9.1.12",
"@angular/platform-browser-dynamic": "9.1.12", "@angular/platform-browser-dynamic": "9.1.12",
"@angular/platform-server": "9.1.12",
"@angular/router": "9.1.12", "@angular/router": "9.1.12",
"@babel/compat-data": "^7.8.0", "@babel/compat-data": "^7.8.0",
"@nguniversal/express-engine": "^9.1.1",
"@turf/centroid": "^5.1.5", "@turf/centroid": "^5.1.5",
"@turf/helpers": "^6.1.4", "@turf/helpers": "^6.1.4",
"@turf/projection": "^6.0.1", "@turf/projection": "^6.0.1",
...@@ -44,6 +50,7 @@ ...@@ -44,6 +50,7 @@
"chart.js": "^2.9.3", "chart.js": "^2.9.3",
"chartjs-plugin-annotation": "^0.5.7", "chartjs-plugin-annotation": "^0.5.7",
"core-js": "^2.5.7", "core-js": "^2.5.7",
"express": "^4.15.2",
"font-awesome": "^4.7.0", "font-awesome": "^4.7.0",
"hamburgers": "^1.1.3", "hamburgers": "^1.1.3",
"jwt-decode": "^2.2.0", "jwt-decode": "^2.2.0",
...@@ -64,6 +71,8 @@ ...@@ -64,6 +71,8 @@
"@angular/cli": "^9.1.12", "@angular/cli": "^9.1.12",
"@angular/compiler-cli": "9.1.12", "@angular/compiler-cli": "9.1.12",
"@angular/language-service": "9.1.12", "@angular/language-service": "9.1.12",
"@nguniversal/builders": "^9.1.1",
"@types/express": "^4.17.0",
"@types/jasmine": "^2.8.12", "@types/jasmine": "^2.8.12",
"@types/jasminewd2": "^2.0.6", "@types/jasminewd2": "^2.0.6",
"@types/jwt-decode": "^2.2.1", "@types/jwt-decode": "^2.2.1",
......
import 'zone.js/dist/zone-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';
// The Express app is exported so that it can be used by serverless Functions.
export function app() {
const server = express();
const distFolder = join(process.cwd(), 'dist/webapp/browser');
const indexHtml = existsSync(join(distFolder, 'index.original.html')) ? 'index.original.html' : 'index';
// Our Universal express-engine (found @ https://github.com/angular/universal/tree/master/modules/express-engine)
server.engine('html', ngExpressEngine({
bootstrap: AppServerModule,
}));
server.set('view engine', 'html');
server.set('views', distFolder);
// Example Express Rest API endpoints
// server.get('/api/**', (req, res) => { });
// Serve static files from /browser
server.get('*.*', express.static(distFolder, {
maxAge: '1y'
}));
// All regular routes use the Universal engine
server.get('*', (req, res) => {
res.render(indexHtml, { req, providers: [{ provide: APP_BASE_HREF, useValue: req.baseUrl }] });
});
return server;
}
function run() {
const port = process.env.PORT || 4000;
// Start up the Node server
const server = app();
server.listen(port, () => {
console.log(`Node Express server listening on http://localhost:${port}`);
});
}
// Webpack will replace 'require' with '__webpack_require__'
// '__non_webpack_require__' is a proxy to Node 'require'
// The below code is to ensure that the server is run only when not requiring the bundle.
declare const __non_webpack_require__: NodeRequire;
const mainModule = __non_webpack_require__.main;
const moduleFilename = mainModule && mainModule.filename || '';
if (moduleFilename === __filename || moduleFilename.includes('iisnode')) {
run();
}
export * from './src/main.server';
import { Component, OnInit } from '@angular/core'; import { Component, OnInit, Inject, PLATFORM_ID } from '@angular/core';
import { Title } from '@angular/platform-browser'; import { Title } from '@angular/platform-browser';
import { Angulartics2Piwik } from 'angulartics2/piwik'; import { Angulartics2Piwik } from 'angulartics2/piwik';
import { filter, map } from 'rxjs/operators'; import { filter, map } from 'rxjs/operators';
...@@ -19,6 +19,7 @@ export class AppComponent implements OnInit { ...@@ -19,6 +19,7 @@ export class AppComponent implements OnInit {
private _activatedRoute: ActivatedRoute, private _activatedRoute: ActivatedRoute,
private _titleService: Title, private _titleService: Title,
private _angulartics2Piwik: Angulartics2Piwik, private _angulartics2Piwik: Angulartics2Piwik,
@Inject(PLATFORM_ID) private _platformId,
) { ) {
this._angulartics2Piwik.startTracking(); this._angulartics2Piwik.startTracking();
} }
......
...@@ -49,7 +49,7 @@ export function initAppConfig(appConfigService: AppConfigService) { ...@@ -49,7 +49,7 @@ export function initAppConfig(appConfigService: AppConfigService) {
AppComponent, AppComponent,
], ],
imports: [ imports: [
BrowserModule, BrowserModule.withServerTransition({ appId: 'serverApp' }),
BrowserAnimationsModule, BrowserAnimationsModule,
HttpClientModule, HttpClientModule,
CoreModule, CoreModule,
......
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 {}
...@@ -48,7 +48,18 @@ export class AppConfigService { ...@@ -48,7 +48,18 @@ export class AppConfigService {
public load() { public load() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const conf = new AppConfig(); const conf = new AppConfig();
APP_CONFIG = Object.assign(conf, window['portailDataEnvConfig']); // Read the dynamic configuration of the application from the json file stored in the assets folder
fetch('./assets/config/config.json')
.then(response => response.json())
.then((config) => {
console.log(config);
if (!config) {
return;
}
// Store the response so that your ConfigService can read it.
APP_CONFIG = Object.assign(conf, config);
});
resolve(); resolve();
}); });
} }
......
import { Injectable } from '@angular/core'; import { Injectable, Inject, PLATFORM_ID } from '@angular/core';
import { isPlatformBrowser } from '@angular/common';
@Injectable() @Injectable()
export class StorageService { export class StorageService {
constructor() { } constructor(
@Inject(PLATFORM_ID) private platformId,
) { }
set(key: string, data: any, lifespan?: number): void { set(key: string, data: any, lifespan?: number): void {
// If time was not defined, set time to 0. 0 is considered infinite so // If time was not defined, set time to 0. 0 is considered infinite so
......
/***************************************************************************************************
* Load `$localize` onto the global scope - used if i18n tags appear in Angular templates.
*/
import '@angular/localize/init';
import { enableProdMode } from '@angular/core';
import { environment } from './environments/environment';
if (environment.production) {
enableProdMode();
}
export { AppServerModule } from './app/app.server.module';
export { renderModule, renderModuleFactory } from '@angular/platform-server';
...@@ -7,18 +7,7 @@ if (environment.production) { ...@@ -7,18 +7,7 @@ if (environment.production) {
enableProdMode(); enableProdMode();
} }
// Read the dynamic configuration of the application from the json file stored in the assets folder document.addEventListener('DOMContentLoaded', () => {
fetch('./assets/config/config.json') platformBrowserDynamic().bootstrapModule(AppModule)
.then(response => response.json()) .catch(err => console.log(err));
.then((config) => { });
if (!config) {
return;
}
// Store the response so that your ConfigService can read it.
window['portailDataEnvConfig'] = config;
platformBrowserDynamic().bootstrapModule(AppModule)
.catch(err => console.log(err));
});
{
"extends": "./tsconfig.app.json",
"compilerOptions": {
"outDir": "../out-tsc/app-server",
"module": "commonjs",
"types": [
"node"
]
},
"files": [
"main.server.ts",
"../server.ts"
],
"angularCompilerOptions": {
"entryModule": "./app/app.server.module#AppServerModule"
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment