Skip to content

Angular 19 forRoot() gets called twice in developer build (v18 only once) #60905

Closed as not planned

Description

@teoeter

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

core

Is this a regression?

Yes

Description

I provide two ng new --standalone=false projects, one in Angular 19 and the other Angular 18.

In the develop build in Angular 19 forRoot will be called twice while in Angular 18 it will be called only once (see console.log output).

For production build both only call forRoot() once.

There is a console.log() in the forRoot() of the TestModule.

Is it a known consequence of the migration from angular 18 to 19 ?

See example code in the attachment.

in v19 forRoot Called will be console logged twice while in v18 it will be once in development build

class TestModule {
  static forRoot(): ModuleWithProviders<TestModule> {
    console.log('forRoot Called');
    return {
      ngModule: TestModule,
    };
  }
}

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    TestModule.forRoot()
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Please provide a link to a minimal reproduction of the bug

See attachment

Archive.zip

Activity

  1. changed the title [-]Angular 19 forRoot() gets called twice[/-] [+]Angular 19 forRoot() gets called twice in developer build (v18 only once)[/+] on Apr 17, 2025
  2. added
    needs reproductionThis issue needs a reproduction in order for the team to investigate further
    on Apr 17, 2025
  3. JeanMeche commented on Apr 17, 2025

    @JeanMeche
    Member

    Interesting, something changed in 19.2.7.
    19.2.6 and previous version do not exhibit this.

    Edit: This is due to #30021.

  4. added
    area: coreIssues related to the framework runtime
    and removed
    needs reproductionThis issue needs a reproduction in order for the team to investigate further
    on Apr 17, 2025
  5. added this to the needsTriage milestone on Apr 17, 2025
  6. JoostK commented on Apr 18, 2025

    @JoostK
    Member

    This behavior itself is tracked in #38376. It started to become relevant for AOT apps again due to angular/angular-cli#30021.

  7. teoeter commented on Apr 18, 2025

    @teoeter
    Author

    This change might not be suited for a patch.

    It could cause some headaches and debugging for library authors who use it for initialization.

    We have a warning in the demo app for the library that appears if forRoot is accidentally initialized twice (a potential regression due to misconfiguration); that's how we detected it.

    The reason is that there might be some logic in a library that should only be done once.
    This can easily be controlled using an already initialized state if Angular doesn't guarantee that it's only done once, and we want the same behavior in development and production.

    If Angular decides to proceed with this, that's fine, but maybe it shouldn't be in a patch release and should be announced in the migration notes.

  8. JoostK commented on Apr 18, 2025

    @JoostK
    Member

    It wasn't a known side-effect of angular/angular-cli#30021 and that issue is fixing a limitation that used to be present for AOT compiled apps in tests, hence it was included in a patch release. Angular's ModuleWithProviders functions are expected to be side-effect free.

    We have a warning in the demo app for the library that appears if forRoot is accidentally initialized twice (a potential regression due to misconfiguration); that's how we detected it.

    How is this done, exactly? I assume this is achieved using some global state that is used as side-channel to detect multiple calls?

  9. alxhub commented on Apr 18, 2025

    @alxhub
    Member

    Closing as a duplicate of #38376, which is now closed as well. In general, this is working as intended. In general, ModuleWithProviders functions shouldn't have side effects. Angular has provideAppInitializer and provideEnvironmentInitializer for adding initialization logic, which is where such validation should take place. A common pattern I've seen is to provide a multiprovider token in forRoot, and use an initializer to check the number of values received for that token. If there's more than one, then forRoot was included too many times.

  10. angular-automatic-lock-bot commented on May 19, 2025

    @angular-automatic-lock-bot

    This issue has been automatically locked due to inactivity.
    Please file a new issue if you are encountering a similar or related problem.

    Read more about our automatic conversation locking policy.

    This action has been performed automatically by a bot.

  11. locked and limited conversation to collaborators on May 19, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: coreIssues related to the framework runtimecore: di

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions