Angular 17 SSR - No tasks executed on server

Discussão em 'Angular' iniciado por Mini Subliminals, Fevereiro 12, 2025.

  1. 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:

    1. It contains 4 Lazy Loaded modules (if this is relevant);
    2. 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 {}

    1. 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 '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/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;

    1. 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:build:production"
    },
    "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:build:production",
    "serverTarget": "AuroraWebApp:server:production"
    }
    },
    "defaultConfiguration": "development"
    },
    "prerender": {
    "builder": "@angular-devkit/build-angular:prerender",
    "options": {
    "routes": [
    "/"
    ]
    },
    "configurations": {
    "production": {
    "browserTarget": "AuroraWebApp:build:production",
    "serverTarget": "AuroraWebApp:server:production"
    },
    "development": {
    "browserTarget": "AuroraWebApp:build:development",
    "serverTarget": "AuroraWebApp:server:development"
    }
    },
    "defaultConfiguration": "production"
    }
    }
    }
    },
    "cli": {
    "cache": {
    "enabled": false
    },
    "analytics": false
    }
    }

    Continue reading...

Compartilhe esta Página