Skip to content

Allow detecting or skipping APP_INITIALIZERs during build-time route-extraction phase, with outputMode: server #32474

@Platonn

Description

@Platonn

Command

build

Description

When building an SSR app with outputMode: 'server', Angular runs a "route extraction" phase to discover all routes for the manifest. The problem is this phase bootstraps our app and runs all APP_INITIALIZERs - including ones that make HTTP calls, etc. which we don't want to run during the build but only during and actual live SSR or actual Prerendering.

These initializers make sense during:

  • Live SSR (handling actual user requests)
  • Prerendering (generating static HTML at build time) - if only we want to do the prerendering (which is not always the case when running the build!)

But during the build (and route extraction), we don't need (or want) to hit our APIs.

Side note: The route extraction phase is executed, even when serverRoutes have no route with Prerender mode.

What we tried:

We dug into the internals and found that ɵSERVER_CONTEXT from @angular/platform-server is the only way to tell these phases apart:

  • Route extraction: null
  • Prerendering: 'ssg'
  • Live SSR: 'ssr'

But since it's a private API (the ɵ prefix), we can't rely on it. We're building an open-source Angular meta-framework for creating ecommerce sites. If we used Angular private API and Angular suddenly changes the private API anytime, we don't want our framework to break for our customers.

We also considered the public tokens REQUEST, RESPONSE_INIT and REQUEST_CONTEXT, but they are all null in both route extraction AND prerendering, so they can't help us distinguish between the two, in case we'd like to run an actual prerendering sometimes.

Describe the solution you'd like

Option A: Let us detect the context

Expose a public token like SERVER_RENDER_CONTEXT (or make ɵSERVER_CONTEXT public) with values like:

  • 'route-extraction' - build-time route discovery
  • 'ssg' - prerendering
  • 'ssr' - live server rendering

Then we could do:

provideAppInitializer(() => {
  const context = inject(SERVER_RENDER_CONTEXT, { optional: true });
  if (context === 'route-extraction') {
    return; // Skip
  }
  // Do the work for actual SSG/SSR
})

Option B: Skip APP_INITIALIZERs during route extraction

Have Angular skip running APP_INITIALIZERs entirely during route extraction, since:

  • Route extraction only needs the Router config
  • It already sets _ENABLE_ROOT_COMPONENT_BOOTSTRAP: false internally
  • Not running initializers would be consistent with that "lightweight" approach

Though it might be risky - some apps might have APP_INITIALIZERS that configure routes dynamically.

Describe alternatives you've considered

  1. Using ɵSERVER_CONTEXT - Works but it's private API, can't use it in a our meta-framework we distribute

  2. Checking REQUEST token - Both route extraction and prerendering have REQUEST: null, so no way to tell them apart 🙁

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions