Skip to content

forRoot() is called twice when imported in app-module (with Ivy only) #38376

Closed as not planned

Description

@Spielboerg

🐞 bug report

Affected Package

The issue is caused by package @angular/core

Is this a regression?

Yes, the previous version in which this bug was not present was: 8 (due to the absence of the Ivy renderer)

Description

If Ivy is enabled, the forRoot() function of imported modules is called twice. However, as the name suggests, it should only be executed once in the app root. If Ivy is disabled or the app is served with --prod, the forRoot() function is called only once, as expected.

In my case this is a problem, because in the forRoot() function I insert an SVG sprite into the DOM, and of course this should only happen once.

🔬 Minimal Reproduction

https://stackblitz.com/edit/angular-10-double-for-root-call?file=src%2Fapp%2Fapp.module.ts

Open the console to see how often the forRoot function is called.

Tip: You can easily enable/disable Ivy in the project settings

The only changes:

  • created a RootModule with a forRoot function
  • added the RootModule to the imports of AppModule and call the forRoot() function

🌍 Your Environment

Angular Version:

Angular CLI: 10.0.5
Node: 12.16.2
OS: darwin x64

Angular: 10.0.8
... animations, common, compiler, compiler-cli, core, forms
... platform-browser, platform-browser-dynamic, router
Ivy Workspace: Yes

Package                           Version
-----------------------------------------------------------
@angular-devkit/architect         0.1000.5
@angular-devkit/build-angular     0.1000.5
@angular-devkit/build-optimizer   0.1000.5
@angular-devkit/build-webpack     0.1000.5
@angular-devkit/core              10.0.5
@angular-devkit/schematics        10.0.5
@angular/cli                      10.0.5
@ngtools/webpack                  10.0.5
@schematics/angular               10.0.5
@schematics/update                0.1000.5
rxjs                              6.6.2
typescript                        3.9.7
webpack                           4.43.0

Activity

  1. JoostK commented on Aug 7, 2020

    @JoostK
    Member

    A quick look at this indicates that that it's called a second time from within the emitted ɵsetClassMetadata call, to capture information for JIT compilations. This is removed in prod-mode, so that explains why it doesn't exist in prod mode.

    The workaround is pretty simple, luckily. You can assign the result of RootModule.forRoot(); into a variable and include that in the list of imports:

    const rootModule = RootModule.forRoot();
    
    @NgModule({
      imports:      [ BrowserModule, FormsModule, rootModule ],
      declarations: [ AppComponent, HelloComponent ],
      bootstrap:    [ AppComponent ]
    })
    export class AppModule { }
  2. added
    area: compilerIssues related to `ngc`, Angular's template compiler
    on Aug 7, 2020
  3. added this to the needsTriage milestone on Aug 7, 2020
  4. Spielboerg commented on Aug 7, 2020

    @Spielboerg
    Author

    @JoostK Thank you for the workaround. It doesn't feel really good, but as a quick workaround it's ok :)

  5. added
    P3An issue that is relevant to core functions, but does not impede progress. Important, but not urgent
    on Oct 17, 2020
  6. modified the milestones: needsTriage, Backlog on Oct 17, 2020
  7. afroguy16 commented on Jan 28, 2021

    @afroguy16

    A quick look at this indicates that that it's called a second time from within the emitted ɵsetClassMetadata call, to capture information for JIT compilations. This is removed in prod-mode, so that explains why it doesn't exist in prod mode.

    The workaround is pretty simple, luckily. You can assign the result of RootModule.forRoot(); into a variable and include that in the list of imports:

    const rootModule = RootModule.forRoot();
    
    @NgModule({
      imports:      [ BrowserModule, FormsModule, rootModule ],
      declarations: [ AppComponent, HelloComponent ],
      bootstrap:    [ AppComponent ]
    })
    export class AppModule { }

    Worked like charm

  8. abhishekmulik commented on Oct 7, 2024

    @abhishekmulik
    import { CommonModule } from '@angular/common';
    import { NgModule } from '@angular/core';
    import { EffectsModule } from '@ngrx/effects';
    import { StoreModule } from '@ngrx/store';
    import { StoreDevtoolsModule } from '@ngrx/store-devtools';
    import { NxModule } from '@nrwl/nx';
    
    import { reducers } from '.';
    import { CustomersEffects } from './customers/customers.effects';
    
    const rootModule = StoreModule.forRoot(reducers);
    
    @NgModule({
      imports: [
        CommonModule,
        NxModule.forRoot(),
        rootModule,
        StoreDevtoolsModule.instrument({ maxAge: 10 }),
        EffectsModule.forRoot([
          CustomersEffects
        ]),
      ],
      declarations: []
    })
    export class StateModule { }
    

    even i do this i am getting the same error

  9. alxhub commented on Apr 18, 2025

    @alxhub
    Member

    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 operations like adding DOM to the document should be configured.

  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

    P3An issue that is relevant to core functions, but does not impede progress. Important, but not urgentarea: compilerIssues related to `ngc`, Angular's template compilercore: NgModuleworkaround1: obvious

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions