Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SSR build prerender broken if configuration has externalDependencies options #29092

Closed
1 task
klerick opened this issue Dec 9, 2024 · 3 comments · Fixed by #29094
Closed
1 task

SSR build prerender broken if configuration has externalDependencies options #29092

klerick opened this issue Dec 9, 2024 · 3 comments · Fixed by #29094
Assignees
Labels
area: @angular/build freq1: low Only reported by a handful of users who observe it rarely severity3: broken type: bug/fix

Comments

@klerick
Copy link

klerick commented Dec 9, 2024

Command

build

Is this a regression?

  • Yes, this behavior used to work in the previous version

The previous version in which this bug was not present was

No response

Description

Dear Angular Team,

We are experiencing an issue with external dependencies when using Angular 19. In our project, we utilize importmap to load external dependencies and have a custom registry hook for resolving these dependencies on our SSR server. However, we encounter an error when attempting to build the project in version 19.

Causes of the Issue:

  1. Dependency Filtering:

  2. Prerendering:

  3. Custom Hook:

Minimal Reproduction

https://stackblitz.com/edit/stackblitz-starters-iudtwvic?file=package.json

npm run build.

Exception or Error


Your Environment

Angular CLI: 19.0.4
Node: 20.13.1
Package Manager: npm 10.5.2
OS: darwin arm64

Angular: 19.0.3
... animations, common, compiler, compiler-cli, core, forms
... language-service, platform-browser, platform-browser-dynamic
... platform-server, router

Package                         Version
---------------------------------------------------------
@angular-devkit/architect       0.1900.4
@angular-devkit/build-angular   19.0.4
@angular-devkit/core            19.0.4
@angular-devkit/schematics      19.0.4
@angular/cdk                    19.0.2
@angular/cli                    19.0.4
@angular/ssr                    19.0.4
@schematics/angular             19.0.4
rxjs                            7.8.1
typescript                      5.6.3
zone.js                         0.15.0

Possible Solutions

  1. Expose partialSSRBuild Configuration:

    • Allow developers to manually configure or override the partialSSRBuild setting. This would provide more control over the build process and help accommodate projects with custom SSR requirements.
  2. Enhance or Extend Custom Hook:

@alan-agius4 alan-agius4 added type: bug/fix freq1: low Only reported by a handful of users who observe it rarely severity3: broken area: @angular/build labels Dec 9, 2024
alan-agius4 added a commit to alan-agius4/angular-cli that referenced this issue Dec 9, 2024
This commit introduces `ngServerMode` to ensure proper handling of external `@angular/` packages when they are used as externals during server-side rendering (SSR).

Closes: angular#29092
alan-agius4 added a commit to alan-agius4/angular-cli that referenced this issue Dec 9, 2024
This commit introduces `ngServerMode` to ensure proper handling of external `@angular/` packages when they are used as externals during server-side rendering (SSR).

Closes: angular#29092
alan-agius4 added a commit to alan-agius4/angular-cli that referenced this issue Dec 9, 2024
This commit introduces `ngServerMode` to ensure proper handling of external `@angular/` packages when they are used as externals during server-side rendering (SSR).

Closes: angular#29092
@alan-agius4 alan-agius4 self-assigned this Dec 9, 2024
alan-agius4 added a commit that referenced this issue Dec 9, 2024
…29094)

This commit introduces `ngServerMode` to ensure proper handling of external `@angular/` packages when they are used as externals during server-side rendering (SSR).

Closes: #29092
(cherry picked from commit d811a7f)
@klerick
Copy link
Author

klerick commented Dec 11, 2024

@alan-agius4

It seems that the problem is not resolved as I initially perceived. I may not have described the issue correctly.

For the SSR build, a worker is used, which launches the server in a separate process. As I understand, the result of this worker is a list of routes for angular-app-manifest.mjs. The worker uses a custom loader.

In our case, we are using a microfrontend architecture. Parts of the application are built and stored on a CDN in one place. We also use a custom loader that emulates the functionality of importmap to load these mini applications.

For example:

import { loadModule } from "@share/utils";

export const appRoutes: Route[] = [{
  path: 'some-path',
  loadChildren: () =>
    loadModule<{ somePartOfRoute: Route, someOtherPartOfRoute: Route }>(
      'uiForgeAppErd/ErdRoutes'
    ).then((r) => [r.somePartOfRoute, r.someOtherPartOfRoute]),
}]

// loadModule is a wrapper for import()
// Resulting in: import('uiForgeAppErd/ErdRoutes')
// We used one config for **importmap** client and SSR
// But I set "uiForgeAppErd/ErdRoutes" as external lib

Since we use a custom loader, we were able to load modules using regular HTTP. This worked in version 18.

However, now the worker cannot load this module because your loader does not recognize 'uiForgeAppErd/ErdRoutes', causing the build to fail.

If we use partialSSRBuild=true, the build completes, but the SSR server does not work because angular-app-manifest.mjs does not contain routes. As a result, the SSR server returns a 404 status.

Is it possible to use SSR without routes in angular-app-manifest.mjs?

Additionally, the build fails if we use an external dependency that can also be resolved through our loader and importmap.
For example:

import { loadModule } from "@share/utils";

console.log(loadModule);

@alan-agius4
Copy link
Collaborator

Hi @klerick, I was wondering if this works with ng serve? Since the modules are external and non-resolvable, I would expect ng serve to fail, or are you disabling SSR while running it? In that case, you'd likely need to provide a Node.js ESM loader for both ng serve and ng build. Unless the semantics of this have changed again, as import hooks in Node.js have been changing frequently. it would be inherited in the worker.

As a workaround, you could try setting the environment variable NG_BUILD_PARTIAL_SSR=1, which would generate a partial manifest. However, this means the manifest would be created at runtime on the first request, unless you're using a serverless or worker environment. In those cases, the manifest might be generated on every request, which could incur a performance penalty. Additionally, validation errors would appear at runtime instead of at build time. Please note that this is not officially part of the public API.

@klerick
Copy link
Author

klerick commented Dec 11, 2024

@alan-agius4
Sorry, it's my mistake.
I had two instance of SERVER_ROUTES_CONFIG%), so serverRoutesConfig in getRoutesFromAngularRouterConfig was undefined.

Now Its working correct))
Thanks!
We are using custom builder, but only for extend for buildApplication and serveWithVite for generate importmap and generate custom hook from import { register } from "module";

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: @angular/build freq1: low Only reported by a handful of users who observe it rarely severity3: broken type: bug/fix
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants