Add: SSR Engine

This commit is contained in:
Luca 2023-10-31 03:30:29 +01:00
parent 5548f9cc04
commit 1ec75c103b
Signed by: lrullo
GPG Key ID: A04E97D8E19A58A7
9 changed files with 1395 additions and 151 deletions

View File

@ -17,7 +17,7 @@
"build": { "build": {
"builder": "@angular-devkit/build-angular:browser", "builder": "@angular-devkit/build-angular:browser",
"options": { "options": {
"outputPath": "dist/cear-rio", "outputPath": "dist/cear-rio/browser",
"index": "src/index.html", "index": "src/index.html",
"main": "src/main.ts", "main": "src/main.ts",
"polyfills": [ "polyfills": [
@ -97,6 +97,61 @@
], ],
"scripts": [] "scripts": []
} }
},
"server": {
"builder": "@angular-devkit/build-angular:server",
"options": {
"outputPath": "dist/cear-rio/server",
"main": "server.ts",
"tsConfig": "tsconfig.server.json",
"inlineStyleLanguage": "scss"
},
"configurations": {
"production": {
"outputHashing": "media"
},
"development": {
"buildOptimizer": false,
"optimization": false,
"sourceMap": true,
"extractLicenses": false,
"vendorChunk": true
}
},
"defaultConfiguration": "production"
},
"serve-ssr": {
"builder": "@nguniversal/builders:ssr-dev-server",
"configurations": {
"development": {
"browserTarget": "cear-rio:build:development",
"serverTarget": "cear-rio:server:development"
},
"production": {
"browserTarget": "cear-rio:build:production",
"serverTarget": "cear-rio:server:production"
}
},
"defaultConfiguration": "development"
},
"prerender": {
"builder": "@nguniversal/builders:prerender",
"options": {
"routes": [
"/"
]
},
"configurations": {
"production": {
"browserTarget": "cear-rio:build:production",
"serverTarget": "cear-rio:server:production"
},
"development": {
"browserTarget": "cear-rio:build:development",
"serverTarget": "cear-rio:server:development"
}
},
"defaultConfiguration": "production"
} }
} }
} }

1379
inc/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -6,7 +6,11 @@
"start": "ng serve", "start": "ng serve",
"build": "ng build", "build": "ng build",
"watch": "ng build --watch --configuration development", "watch": "ng build --watch --configuration development",
"test": "ng test" "test": "ng test",
"dev:ssr": "ng run cear-rio:serve-ssr",
"serve:ssr": "node dist/cear-rio/server/main.js",
"build:ssr": "ng build && ng run cear-rio:server",
"prerender": "ng run cear-rio:prerender"
}, },
"private": true, "private": true,
"dependencies": { "dependencies": {
@ -17,7 +21,10 @@
"@angular/forms": "^16.2.0", "@angular/forms": "^16.2.0",
"@angular/platform-browser": "^16.2.0", "@angular/platform-browser": "^16.2.0",
"@angular/platform-browser-dynamic": "^16.2.0", "@angular/platform-browser-dynamic": "^16.2.0",
"@angular/platform-server": "^16.2.0",
"@angular/router": "^16.2.0", "@angular/router": "^16.2.0",
"@nguniversal/express-engine": "^16.2.0",
"express": "^4.15.2",
"rxjs": "~7.8.0", "rxjs": "~7.8.0",
"tslib": "^2.3.0", "tslib": "^2.3.0",
"zone.js": "~0.13.0" "zone.js": "~0.13.0"
@ -26,7 +33,10 @@
"@angular-devkit/build-angular": "^16.2.8", "@angular-devkit/build-angular": "^16.2.8",
"@angular/cli": "^16.2.8", "@angular/cli": "^16.2.8",
"@angular/compiler-cli": "^16.2.0", "@angular/compiler-cli": "^16.2.0",
"@nguniversal/builders": "^16.2.0",
"@types/express": "^4.17.0",
"@types/jasmine": "~4.3.0", "@types/jasmine": "~4.3.0",
"@types/node": "^16.11.7",
"jasmine-core": "~4.6.0", "jasmine-core": "~4.6.0",
"karma": "~6.4.0", "karma": "~6.4.0",
"karma-chrome-launcher": "~3.2.0", "karma-chrome-launcher": "~3.2.0",
@ -35,4 +45,4 @@
"karma-jasmine-html-reporter": "~2.1.0", "karma-jasmine-html-reporter": "~2.1.0",
"typescript": "~5.1.3" "typescript": "~5.1.3"
} }
} }

59
inc/server.ts Normal file
View File

@ -0,0 +1,59 @@
import 'zone.js/node';
import { APP_BASE_HREF } from '@angular/common';
import { ngExpressEngine } from '@nguniversal/express-engine';
import * as express from 'express';
import { existsSync } from 'node:fs';
import { join } from 'node:path';
import { AppServerModule } from './src/main.server';
// The Express app is exported so that it can be used by serverless Functions.
export function app(): express.Express {
const server = express();
const distFolder = join(process.cwd(), 'dist/cear-rio/browser');
const indexHtml = existsSync(join(distFolder, 'index.original.html')) ? 'index.original.html' : 'index';
// Our Universal express-engine (found @ https://github.com/angular/universal/tree/main/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(): void {
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';

View File

@ -4,7 +4,9 @@ import { RouterModule, Routes } from '@angular/router';
const routes: Routes = []; const routes: Routes = [];
@NgModule({ @NgModule({
imports: [RouterModule.forRoot(routes)], imports: [RouterModule.forRoot(routes, {
initialNavigation: 'enabledBlocking'
})],
exports: [RouterModule] exports: [RouterModule]
}) })
export class AppRoutingModule { } export class AppRoutingModule { }

View File

@ -8,6 +8,8 @@ import { PlayerService } from './player.service';
import { HttpClientModule } from '@angular/common/http'; import { HttpClientModule } from '@angular/common/http';
import { HeaderComponent } from './header/header.component'; import { HeaderComponent } from './header/header.component';
import {provideClientHydration} from '@angular/platform-browser';
@NgModule({ @NgModule({
declarations: [ declarations: [
AppComponent, AppComponent,
@ -19,6 +21,7 @@ import { HeaderComponent } from './header/header.component';
HttpClientModule HttpClientModule
], ],
providers: [ providers: [
provideClientHydration(),
PlayerService PlayerService
], ],
bootstrap: [AppComponent] bootstrap: [AppComponent]

View File

@ -0,0 +1,14 @@
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
inc/src/main.server.ts Normal file
View File

@ -0,0 +1,2 @@
export { AppServerModule } from './app/app.server.module';

14
inc/tsconfig.server.json Normal file
View File

@ -0,0 +1,14 @@
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"extends": "./tsconfig.app.json",
"compilerOptions": {
"outDir": "./out-tsc/server",
"types": [
"node"
]
},
"files": [
"src/main.server.ts",
"server.ts"
]
}