diff --git a/.gitignore b/.gitignore
index edbcb36..314dbb2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -42,3 +42,5 @@ testem.log
.DS_Store
Thumbs.db
documentation
+
+/.nx
\ No newline at end of file
diff --git a/.npmrc b/.npmrc
new file mode 100644
index 0000000..edb51a1
--- /dev/null
+++ b/.npmrc
@@ -0,0 +1,3 @@
+# auto-install-peers=true
+shamefully-hoist=true
+node-linker=hoisted
\ No newline at end of file
diff --git a/angular.json b/angular.json
index 6dc634c..d3abbfc 100644
--- a/angular.json
+++ b/angular.json
@@ -23,7 +23,7 @@
"allowedCommonJsDependencies": [
"lodash.isequal"
],
- "outputPath": "dist/application",
+ "outputPath": "dist/application/browser",
"index": "application/src/index.html",
"main": "application/src/main.ts",
"polyfills": [
@@ -81,10 +81,10 @@
},
"configurations": {
"production": {
- "browserTarget": "application:build:production"
+ "buildTarget": "application:build:production"
},
"development": {
- "browserTarget": "application:build:development"
+ "buildTarget": "application:build:development"
}
},
"defaultConfiguration": "development"
@@ -92,7 +92,7 @@
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
- "browserTarget": "application:build"
+ "buildTarget": "application:build"
}
},
"test": {
@@ -126,6 +126,61 @@
"options": {
"lintFilePatterns": ["application/src/**/*.{ts,html,js,json}"]
}
+ },
+ "server": {
+ "builder": "@angular-devkit/build-angular:server",
+ "options": {
+ "outputPath": "dist/application/server",
+ "main": "application/server.ts",
+ "tsConfig": "application/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": {
+ "buildTarget": "application:build:development",
+ "serverTarget": "application:server:development"
+ },
+ "production": {
+ "buildTarget": "application:build:production",
+ "serverTarget": "application:server:production"
+ }
+ },
+ "defaultConfiguration": "development"
+ },
+ "prerender": {
+ "builder": "@nguniversal/builders:prerender",
+ "options": {
+ "routes": [
+ "/"
+ ]
+ },
+ "configurations": {
+ "production": {
+ "buildTarget": "application:build:production",
+ "serverTarget": "application:server:production"
+ },
+ "development": {
+ "buildTarget": "application:build:development",
+ "serverTarget": "application:server:development"
+ }
+ },
+ "defaultConfiguration": "production"
}
}
},
diff --git a/application/server.ts b/application/server.ts
new file mode 100644
index 0000000..4c6addc
--- /dev/null
+++ b/application/server.ts
@@ -0,0 +1,56 @@
+import { APP_BASE_HREF } from '@angular/common'
+import { CommonEngine } from '@angular/ssr'
+import express from 'express'
+import { fileURLToPath } from 'node:url'
+import { dirname, join, resolve } from 'node:path'
+import bootstrap 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 serverDistFolder = dirname(fileURLToPath(import.meta.url))
+ const browserDistFolder = resolve(serverDistFolder, '../browser')
+ const indexHtml = join(serverDistFolder, 'index.server.html')
+
+ const commonEngine = new CommonEngine()
+
+ server.set('view engine', 'html')
+ server.set('views', browserDistFolder)
+
+ // Example Express Rest API endpoints
+ // server.get('/api/**', (req, res) => { });
+ // Serve static files from /browser
+ server.get('*.*', express.static(browserDistFolder, {
+ maxAge: '1y'
+ }))
+
+ // All regular routes use the Angular engine
+ server.get('*', (req, res, next) => {
+ const { protocol, originalUrl, baseUrl, headers } = req
+
+ commonEngine
+ .render({
+ bootstrap,
+ documentFilePath: indexHtml,
+ url: `${protocol}://${headers.host}${originalUrl}`,
+ publicPath: browserDistFolder,
+ providers: [{ provide: APP_BASE_HREF, useValue: baseUrl }],
+ })
+ .then((html) => res.send(html))
+ .catch((err) => next(err))
+ })
+
+ 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}`)
+ })
+}
+
+run()
diff --git a/application/src/app/app-routing.module.ts b/application/src/app/app-routing.module.ts
index defbff1..36004d3 100644
--- a/application/src/app/app-routing.module.ts
+++ b/application/src/app/app-routing.module.ts
@@ -1,7 +1,7 @@
import { NgModule } from '@angular/core'
import { RouterModule, Routes } from '@angular/router'
-const routes: Routes = []
+export const routes: Routes = []
@NgModule({
imports: [RouterModule.forRoot(routes)],
diff --git a/application/src/app/app.component.html b/application/src/app/app.component.html
index dfa3a07..977a895 100644
--- a/application/src/app/app.component.html
+++ b/application/src/app/app.component.html
@@ -4,4 +4,4 @@
-
\ No newline at end of file
+
diff --git a/application/src/app/app.component.ts b/application/src/app/app.component.ts
index 238bf6c..2aa76ef 100644
--- a/application/src/app/app.component.ts
+++ b/application/src/app/app.component.ts
@@ -1,4 +1,6 @@
-import { Component, OnInit } from '@angular/core'
+import { DOCUMENT, isPlatformServer } from '@angular/common'
+import { Component, Inject, InjectionToken, OnInit, PLATFORM_ID } from '@angular/core'
+import { GetWindow } from 'src/helpers/window.helper'
@Component({
@@ -7,19 +9,27 @@ import { Component, OnInit } from '@angular/core'
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
- theme = window.matchMedia('(prefers-color-scheme:dark)').matches ? 'dark' : 'light'
+ isServer = isPlatformServer(this.platformId)
+ constructor(@Inject(PLATFORM_ID) private platformId: InjectionToken