|
@@ -39,7 +39,15 @@
|
|
| 39 |
"styles": [
|
| 40 |
"src/styles.css"
|
| 41 |
],
|
| 42 |
-
"scripts": []
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 43 |
},
|
| 44 |
"configurations": {
|
| 45 |
"production": {
|
| 39 |
"styles": [
|
| 40 |
"src/styles.css"
|
| 41 |
],
|
| 42 |
+
"scripts": [],
|
| 43 |
+
"server": "src/main.server.ts",
|
| 44 |
+
"prerender": {
|
| 45 |
+
"discoverRoutes": true,
|
| 46 |
+
"routesFile": "routes.txt"
|
| 47 |
+
},
|
| 48 |
+
"ssr": {
|
| 49 |
+
"entry": "src/server.ts"
|
| 50 |
+
}
|
| 51 |
},
|
| 52 |
"configurations": {
|
| 53 |
"production": {
|
|
@@ -7,7 +7,8 @@
|
|
| 7 |
"build": "ng build",
|
| 8 |
"watch": "ng build --watch --configuration development",
|
| 9 |
"test": "ng test",
|
| 10 |
-
"lint": "ng lint"
|
|
|
|
| 11 |
},
|
| 12 |
"private": true,
|
| 13 |
"dependencies": {
|
|
@@ -18,9 +19,12 @@
|
|
| 18 |
"@angular/forms": "^19.2.0",
|
| 19 |
"@angular/platform-browser": "^19.2.0",
|
| 20 |
"@angular/platform-browser-dynamic": "^19.2.0",
|
|
|
|
| 21 |
"@angular/router": "^19.2.0",
|
|
|
|
| 22 |
"angular-date-value-accessor": "^3.0.0",
|
| 23 |
"book-monkey5-styles": "^1.0.4",
|
|
|
|
| 24 |
"rxjs": "~7.8.0",
|
| 25 |
"tslib": "^2.3.0",
|
| 26 |
"zone.js": "~0.15.0"
|
|
@@ -29,7 +33,9 @@
|
|
| 29 |
"@angular-devkit/build-angular": "^19.2.1",
|
| 30 |
"@angular/cli": "^19.2.1",
|
| 31 |
"@angular/compiler-cli": "^19.2.0",
|
|
|
|
| 32 |
"@types/jasmine": "~5.1.0",
|
|
|
|
| 33 |
"angular-eslint": "19.2.0",
|
| 34 |
"eslint": "^9.21.0",
|
| 35 |
"jasmine-core": "~5.6.0",
|
|
@@ -41,4 +47,4 @@
|
|
| 41 |
"typescript": "~5.7.2",
|
| 42 |
"typescript-eslint": "8.25.0"
|
| 43 |
}
|
| 44 |
-
}
|
| 7 |
"build": "ng build",
|
| 8 |
"watch": "ng build --watch --configuration development",
|
| 9 |
"test": "ng test",
|
| 10 |
+
"lint": "ng lint",
|
| 11 |
+
"serve:ssr:book-monkey": "node dist/book-monkey/server/server.mjs"
|
| 12 |
},
|
| 13 |
"private": true,
|
| 14 |
"dependencies": {
|
| 19 |
"@angular/forms": "^19.2.0",
|
| 20 |
"@angular/platform-browser": "^19.2.0",
|
| 21 |
"@angular/platform-browser-dynamic": "^19.2.0",
|
| 22 |
+
"@angular/platform-server": "^19.2.0",
|
| 23 |
"@angular/router": "^19.2.0",
|
| 24 |
+
"@angular/ssr": "^19.2.1",
|
| 25 |
"angular-date-value-accessor": "^3.0.0",
|
| 26 |
"book-monkey5-styles": "^1.0.4",
|
| 27 |
+
"express": "^4.18.2",
|
| 28 |
"rxjs": "~7.8.0",
|
| 29 |
"tslib": "^2.3.0",
|
| 30 |
"zone.js": "~0.15.0"
|
| 33 |
"@angular-devkit/build-angular": "^19.2.1",
|
| 34 |
"@angular/cli": "^19.2.1",
|
| 35 |
"@angular/compiler-cli": "^19.2.0",
|
| 36 |
+
"@types/express": "^4.17.17",
|
| 37 |
"@types/jasmine": "~5.1.0",
|
| 38 |
+
"@types/node": "^18.18.0",
|
| 39 |
"angular-eslint": "19.2.0",
|
| 40 |
"eslint": "^9.21.0",
|
| 41 |
"jasmine-core": "~5.6.0",
|
| 47 |
"typescript": "~5.7.2",
|
| 48 |
"typescript-eslint": "8.25.0"
|
| 49 |
}
|
| 50 |
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/
|
| 2 |
+
/home
|
| 3 |
+
/books
|
| 4 |
+
/books/9783864909467
|
| 5 |
+
/books/9783864907791
|
| 6 |
+
/books/9783864906466
|
| 7 |
+
/books/9783864903571
|
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { NgModule } from '@angular/core';
|
| 2 |
+
import { ServerModule } from '@angular/platform-server';
|
| 3 |
+
|
| 4 |
+
import { AppModule } from './app.module';
|
| 5 |
+
import { AppComponent } from './app.component';
|
| 6 |
+
|
| 7 |
+
@NgModule({
|
| 8 |
+
imports: [
|
| 9 |
+
AppModule,
|
| 10 |
+
ServerModule,
|
| 11 |
+
],
|
| 12 |
+
bootstrap: [AppComponent],
|
| 13 |
+
})
|
| 14 |
+
export class AppServerModule {}
|
|
@@ -1,6 +1,6 @@
|
|
| 1 |
import { NgModule } from '@angular/core';
|
| 2 |
import { provideHttpClient, withInterceptorsFromDi, HTTP_INTERCEPTORS } from '@angular/common/http';
|
| 3 |
-
import { BrowserModule } from '@angular/platform-browser';
|
| 4 |
|
| 5 |
import { AppRoutingModule } from './app-routing.module';
|
| 6 |
import { AppComponent } from './app.component';
|
|
@@ -24,7 +24,8 @@ import { AuthInterceptor } from './shared/auth.interceptor';
|
|
| 24 |
provide: HTTP_INTERCEPTORS,
|
| 25 |
useClass: AuthInterceptor,
|
| 26 |
multi: true
|
| 27 |
-
}
|
|
|
|
| 28 |
],
|
| 29 |
bootstrap: [AppComponent]
|
| 30 |
})
|
| 1 |
import { NgModule } from '@angular/core';
|
| 2 |
import { provideHttpClient, withInterceptorsFromDi, HTTP_INTERCEPTORS } from '@angular/common/http';
|
| 3 |
+
import { BrowserModule, provideClientHydration } from '@angular/platform-browser';
|
| 4 |
|
| 5 |
import { AppRoutingModule } from './app-routing.module';
|
| 6 |
import { AppComponent } from './app.component';
|
| 24 |
provide: HTTP_INTERCEPTORS,
|
| 25 |
useClass: AuthInterceptor,
|
| 26 |
multi: true
|
| 27 |
+
},
|
| 28 |
+
provideClientHydration()
|
| 29 |
],
|
| 30 |
bootstrap: [AppComponent]
|
| 31 |
})
|
|
@@ -0,0 +1 @@
|
|
|
|
| 1 |
+
export { AppServerModule as default } from './app/app.module.server';
|
|
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { APP_BASE_HREF } from '@angular/common';
|
| 2 |
+
import { CommonEngine, isMainModule } from '@angular/ssr/node';
|
| 3 |
+
import express from 'express';
|
| 4 |
+
import { dirname, join, resolve } from 'node:path';
|
| 5 |
+
import { fileURLToPath } from 'node:url';
|
| 6 |
+
import AppServerModule from './main.server';
|
| 7 |
+
|
| 8 |
+
const serverDistFolder = dirname(fileURLToPath(import.meta.url));
|
| 9 |
+
const browserDistFolder = resolve(serverDistFolder, '../browser');
|
| 10 |
+
const indexHtml = join(serverDistFolder, 'index.server.html');
|
| 11 |
+
|
| 12 |
+
const app = express();
|
| 13 |
+
const commonEngine = new CommonEngine();
|
| 14 |
+
|
| 15 |
+
/**
|
| 16 |
+
* Example Express Rest API endpoints can be defined here.
|
| 17 |
+
* Uncomment and define endpoints as necessary.
|
| 18 |
+
*
|
| 19 |
+
* Example:
|
| 20 |
+
* ```ts
|
| 21 |
+
* app.get('/api/**', (req, res) => {
|
| 22 |
+
* // Handle API request
|
| 23 |
+
* });
|
| 24 |
+
* ```
|
| 25 |
+
*/
|
| 26 |
+
|
| 27 |
+
/**
|
| 28 |
+
* Serve static files from /browser
|
| 29 |
+
*/
|
| 30 |
+
app.get(
|
| 31 |
+
'**',
|
| 32 |
+
express.static(browserDistFolder, {
|
| 33 |
+
maxAge: '1y',
|
| 34 |
+
index: 'index.html'
|
| 35 |
+
}),
|
| 36 |
+
);
|
| 37 |
+
|
| 38 |
+
/**
|
| 39 |
+
* Handle all other requests by rendering the Angular application.
|
| 40 |
+
*/
|
| 41 |
+
app.get('**', (req, res, next) => {
|
| 42 |
+
const { protocol, originalUrl, baseUrl, headers } = req;
|
| 43 |
+
|
| 44 |
+
commonEngine
|
| 45 |
+
.render({
|
| 46 |
+
bootstrap: AppServerModule,
|
| 47 |
+
documentFilePath: indexHtml,
|
| 48 |
+
url: `${protocol}://${headers.host}${originalUrl}`,
|
| 49 |
+
publicPath: browserDistFolder,
|
| 50 |
+
providers: [{ provide: APP_BASE_HREF, useValue: baseUrl }],
|
| 51 |
+
})
|
| 52 |
+
.then((html) => res.send(html))
|
| 53 |
+
.catch((err) => next(err));
|
| 54 |
+
});
|
| 55 |
+
|
| 56 |
+
/**
|
| 57 |
+
* Start the server if this module is the main entry point.
|
| 58 |
+
* The server listens on the port defined by the `PORT` environment variable, or defaults to 4000.
|
| 59 |
+
*/
|
| 60 |
+
if (isMainModule(import.meta.url)) {
|
| 61 |
+
const port = process.env['PORT'] || 4000;
|
| 62 |
+
app.listen(port, () => {
|
| 63 |
+
console.log(`Node Express server listening on http://localhost:${port}`);
|
| 64 |
+
});
|
| 65 |
+
}
|
| 66 |
+
|
| 67 |
+
export default app;
|
|
@@ -4,10 +4,14 @@
|
|
| 4 |
"extends": "./tsconfig.json",
|
| 5 |
"compilerOptions": {
|
| 6 |
"outDir": "./out-tsc/app",
|
| 7 |
-
"types": [
|
|
|
|
|
|
|
| 8 |
},
|
| 9 |
"files": [
|
| 10 |
-
"src/main.ts"
|
|
|
|
|
|
|
| 11 |
],
|
| 12 |
"include": [
|
| 13 |
"src/**/*.d.ts"
|
| 4 |
"extends": "./tsconfig.json",
|
| 5 |
"compilerOptions": {
|
| 6 |
"outDir": "./out-tsc/app",
|
| 7 |
+
"types": [
|
| 8 |
+
"node"
|
| 9 |
+
]
|
| 10 |
},
|
| 11 |
"files": [
|
| 12 |
+
"src/main.ts",
|
| 13 |
+
"src/main.server.ts",
|
| 14 |
+
"src/server.ts"
|
| 15 |
],
|
| 16 |
"include": [
|
| 17 |
"src/**/*.d.ts"
|