Skip to content

Issue with SSR: intermittent errors under load #58526

@kinkaz

Description

@kinkaz

Which @angular/* package(s) are the source of the bug?

platform-server

Is this a regression?

No

Description

When using SSR in my app, we intermittently encounter error pages under load. Here are two examples of errors observed:

  • TypeError: this._platformLocation.getBaseHrefFromDOM is not a function
  • ReferenceError: document is not defined

I think it's related to the SSR failing (crash).

Steps to Reproduce

Open the website and hit the refresh button ~10 times quickly. This reliably triggers the errors, simulating the load scenario.

Background

  • Before updating Angular from 18.2.4 to 18.2.10, SSR would fail under load, and restarting the server (pm2 restart) was required to resolve it.
  • After updating to 18.2.10 (following this Angular PR), the error still occurs, but now a single page refresh is enough to resolve it, so a server restart is no longer needed. It still a big issue as I guess users won't necessarily try to refresh the page on their own.

Additional Information

The application uses Nx and pm2 to start the server on the hosting service.

Any insights on what could be causing this intermittent error would be greatly appreciated.

Please provide a link to a minimal reproduction of the bug

https://test.particip.swiss/passer-mon-permis/permis-de-conduire-voiture-b

Please provide the exception or error you saw

ReferenceError: document is not defined
at Object.Mx [as useFactory] (file:///home/clients/xyz/sites/test.particip.swiss/server/chunk-3O22WMVP.mjs:35:29288)
at Object.r [as factory] (file:///home/clients/xyz/sites/test.particip.swiss/server/chunk-3O22WMVP.mjs:8:12430)
at Ks.hydrate (file:///home/clients/xyz/sites/test.particip.swiss/server/chunk-3O22WMVP.mjs:8:11571)
at Ks.get (file:///home/clients/xyz/sites/test.particip.swiss/server/chunk-3O22WMVP.mjs:8:10685)
at hT (file:///home/clients/xyz/sites/test.particip.swiss/server/chunk-3O22WMVP.mjs:5:2448)
at re (file:///home/clients/xyz/sites/test.particip.swiss/server/chunk-3O22WMVP.mjs:5:2527)
at Z (file:///home/clients/xyz/sites/test.particip.swiss/server/chunk-3O22WMVP.mjs:5:2571)
at new e (file:///home/clients/xyz/sites/test.particip.swiss/server/chunk-3O22WMVP.mjs:34:80191)
at Object.factory (file:///home/clients/xyz/sites/test.particip.swiss/server/chunk-3O22WMVP.mjs:34:81271)
at Ks.hydrate (file:///home/clients/xyz/sites/test.particip.swiss/server/chunk-3O22WMVP.mjs:8:11571)

Please provide the environment you discovered this bug in (run ng version)

Angular CLI: 18.2.10
Node: 20.10.0
Package Manager: npm 10.2.3
OS: darwin arm64

Angular: 18.2.10
... animations, cdk, cli, common, compiler, compiler-cli, core
... elements, forms, language-service, localize
... platform-browser, platform-browser-dynamic, platform-server
... router, ssr

Package Version

@angular-devkit/architect 0.1802.6
@angular-devkit/build-angular 18.2.10
@angular-devkit/core 18.2.10
@angular-devkit/schematics 18.2.10
@angular/fire 18.0.1
@schematics/angular 18.2.10
rxjs 7.8.1
typescript 5.5.4
zone.js 0.14.10

Anything else?

I'm using Nx and pm2 the start the server on the hosting service.

Here's my server.ts :

import 'zone.js/node';
import { CommonEngine } from '@angular/ssr';
import express from 'express';
import { dirname, join, resolve } from 'node:path';
import bootstrap from './src/main.server';
import { environment } from './src/environments/environment';
import { fileURLToPath } from 'node:url';
import { APP_BASE_HREF } from '@angular/common';

// 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',
      index: 'index.html',
    }),
  );

  // 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 = environment.ssrPort;

  // Start up the Node server
  const server = app();
  server.listen(port, () => {
    console.log(`Node Express server listening on http://localhost:${port}`);
  });
}

run();

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: serverIssues related to server-side renderingneeds reproductionThis issue needs a reproduction in order for the team to investigate further

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions