Recently, I updated an Angular project from version 16 to version 17. Today, I decided to add SSR to the project. The project is running with no problems when served using npm run dev:ssr, and the HTML is being rendered on the server side, but no logic written in TypeScript is being executed on server at all, and I need some things to be executed on server. For example, this is the constructor of my AppComponent: constructor( private _router: Router, @Inject(PLATFORM_ID) private platformId: Object) { console.log(isPlatformServer(this.platformId) ? 'Server' : 'Client'); } And it is always being executed in browser for some reason, but I need to write some code that's gonna be executed on server first. I think my project might be improperly configured, but I'm not sure where to find the solution. Further info about the project: It contains 4 Lazy Loaded modules (if this is relevant); Here's my AppServerModule code: import { NgModule } from "@angular/core"; import { ServerModule } from "@angular/platform-server"; import { AppModule } from "./app.module"; import { AppComponent } from "./app.component"; import { FlexLayoutServerModule } from "@ngbracket/ngx-layout/server"; @NgModule({ imports: [AppModule, ServerModule, FlexLayoutServerModule], bootstrap: [AppComponent] }) export class AppServerModule {} Here's my server.ts: import 'zone.js/node'; import { APP_BASE_HREF } from '@angular/common'; import { CommonEngine } from '@angular/ssr'; import * as express from 'express'; import { existsSync } from 'node:fs'; import { join } from 'nodeath'; 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/KempaWebApp/browser'); const indexHtml = existsSync(join(distFolder, 'index.original.html')) ? join(distFolder, 'index.original.html') : join(distFolder, 'index.html'); const commonEngine = new CommonEngine(); 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 Angular engine server.get('*', (req, res, next) => { const { protocol, originalUrl, baseUrl, headers } = req; commonEngine .render({ bootstrap: AppServerModule, documentFilePath: indexHtml, url: `${protocol}://${headers.host}${originalUrl}`, publicPath: distFolder, 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}`); }); } // 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 default AppServerModule; This is what I have in main.server.ts: export { AppServerModule as default } from './app/app.module.server'; If there's any other relevant info I can provide, please, ask me in the comment. UPDATE: Here's my angular.json: { "$schema": "./node_modules/@angular/cli/lib/config/schema.json", "version": 1, "newProjectRoot": "projects", "projects": { "AuroraWebApp": { "projectType": "application", "schematics": { "@schematics/angular:component": { "style": "scss" }, "@schematics/angular:application": { "strict": false } }, "root": "", "sourceRoot": "src", "prefix": "app", "architect": { "build": { "builder": "@angular-devkit/build-angular:browser", "options": { "outputPath": "dist/AuroraWebApp/browser", "index": "src/index.html", "main": "src/main.ts", "polyfills": [ "zone.js" ], "tsConfig": "tsconfig.app.json", "inlineStyleLanguage": "scss", "assets": [ "src/favicon.ico", "src/assets", "src/robots.txt", "src/sitemap.xml" ], "styles": [ "src/styles.scss" ], "scripts": [] }, "configurations": { "production": { "budgets": [ { "type": "initial", "maximumWarning": "500kb", "maximumError": "2mb" }, { "type": "anyComponentStyle", "maximumWarning": "2kb", "maximumError": "10kb" } ], "index": { "input": "src/index.prod.html", "output": "index.html" }, "fileReplacements": [ { "replace": "src/environments/environment.ts", "with": "src/environments/environment.prod.ts" } ], "outputHashing": "all" }, "staging": { "budgets": [ { "type": "initial", "maximumWarning": "500kb", "maximumError": "2mb" }, { "type": "anyComponentStyle", "maximumWarning": "2kb", "maximumError": "10kb" } ], "fileReplacements": [ { "replace": "src/environments/environment.ts", "with": "src/environments/environment.staging.ts" } ], "outputHashing": "all" }, "development": { "buildOptimizer": false, "optimization": false, "vendorChunk": true, "extractLicenses": false, "sourceMap": true, "namedChunks": true } }, "defaultConfiguration": "production" }, "serve": { "builder": "@angular-devkit/build-angular:dev-server", "configurations": { "production": { "buildTarget": "AuroraWebApp:buildroduction" }, "development": { "buildTarget": "AuroraWebApp:build:development" } }, "defaultConfiguration": "development" }, "extract-i18n": { "builder": "@angular-devkit/build-angular:extract-i18n", "options": { "buildTarget": "AuroraWebApp:build" } }, "test": { "builder": "@angular-devkit/build-angular:karma", "options": { "polyfills": [ "zone.js", "zone.js/testing" ], "tsConfig": "tsconfig.spec.json", "inlineStyleLanguage": "scss", "assets": [ "src/favicon.ico", "src/assets", "src/robots.txt", "src/sitemap.xml" ], "styles": [ "src/styles.scss" ], "scripts": [] } }, "server": { "builder": "@angular-devkit/build-angular:server", "options": { "outputPath": "dist/AuroraWebApp/server", "main": "server.ts", "tsConfig": "tsconfig.server.json", "inlineStyleLanguage": "scss" }, "configurations": { "production": { "outputHashing": "media", "fileReplacements": [ { "replace": "src/environments/environment.ts", "with": "src/environments/environment.prod.ts" } ] }, "staging": { "outputHashing": "media", "fileReplacements": [ { "replace": "src/environments/environment.ts", "with": "src/environments/environment.staging.ts" } ] }, "development": { "buildOptimizer": false, "optimization": false, "sourceMap": true, "extractLicenses": false, "vendorChunk": true } }, "defaultConfiguration": "production" }, "serve-ssr": { "builder": "@angular-devkit/build-angular:ssr-dev-server", "configurations": { "development": { "browserTarget": "AuroraWebApp:build:development", "serverTarget": "AuroraWebApp:server:development" }, "production": { "browserTarget": "AuroraWebApp:buildroduction", "serverTarget": "AuroraWebApp:serverroduction" } }, "defaultConfiguration": "development" }, "prerender": { "builder": "@angular-devkit/build-angularrerender", "options": { "routes": [ "/" ] }, "configurations": { "production": { "browserTarget": "AuroraWebApp:buildroduction", "serverTarget": "AuroraWebApp:serverroduction" }, "development": { "browserTarget": "AuroraWebApp:build:development", "serverTarget": "AuroraWebApp:server:development" } }, "defaultConfiguration": "production" } } } }, "cli": { "cache": { "enabled": false }, "analytics": false } } Continue reading...