6

I have a lazy load module which needs to expose providers, so I am using the forRoot convention and returning the following code:

@NgModule({
  imports: [RouterModule.forChild([
    {path: "", component: LazyComponent},
  ])],
  declarations: [LazyComponent],
})
export class LazyModule {
  static forRoot() {
    return {
      ngModule: LazyModule,
      providers: [provider]
    };
  }
}

The problem is when I invoke the forRoot in my app module the lazy load does not work anymore. ( I don't see the separate chunk in my console )

@NgModule({
  declarations: [
    AppComponent,
    HelloComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    LazyModule.forRoot() <======== this stops the lazy load module
  ],
  bootstrap: [AppComponent]
})
export class AppModule {
}

From what I learned it should only make the providers singleton, why it does not work?

3
  • 1
    If you import LazyLoad module in eager module then webpack won't create chunk for it Commented Feb 3, 2018 at 20:53
  • So what you are saying is that I can't get lazy load my modules and use forRoot at the same time? Commented Feb 3, 2018 at 20:56
  • You can create separate module that contains only providers and import it Commented Feb 3, 2018 at 20:57

5 Answers 5

6

As of right now, it's not possible to execute a forRoot (or any other configuration static method of this sort) in a module that will load lazily. The problem here is that such a method returns a ModuleWithProviders while loadChildren requires a NgModuleFactory.

Sign up to request clarification or add additional context in comments.

Comments

2

I faced a similar issue where I had to lazy load a module with some configurations. So, I came up with this temporary fix.

Lazy Module

    @NgModule({
          imports: [
             RouterModule.forChild([
              {path: "", component: LazyComponent},
             ])],
          declarations: [LazyComponent],
    })
    export class LazyModule {
       // considering the function only handle providers 
       static setDynamicProviders(provider?: any) {
            if(LazyModule && LazyModule.__annotations__ && LazyModule.__annotations__[0]){
            LazyModule.__annotations__[0].providers.push(provider);               
          }
            return LazyModule;
       }
   }

Parent Module

const someService = {
  provide: 'SOME_TOKEN',
  useFactory: (dependecy1) => (//dome something with dependency1)
  deps: [SOME_DEPENDENCY_TOKEN]
}

@NgModule({
 imports: [
    RouterModule.forRoot([
        path: 'lazy',
        loadChildren: ()=>(import('*your path to lazy module*').then(ref => ref.LazyModule.setDynamicProvider(someService)))
    ])
  ]
})

So, I am just modifying the annotations created by @NgModule Decorator. At this stage, Angular does not support lazy loading with static methods that return ModuleWithProviders.

1 Comment

In case of 13th version you can push a provider as LazyModule['ɵinj'].providers.push(provider)
1

When you import a LazyModule in your AppModule imports array it is not "lazy" anymore. A lazy module should only be referenced in a dedicated RoutingModule.

So if I understood you correctly you would like to share a Service between your LazyModules?

If so remove LazyModule from AppModule and create a SharedModule and move your Service you like to share inside the providers array in SharedModule. Import SharedModule in your AppModule with forRoot and import your SharedModule without forRoot in your LazyModules

Comments

0

Try below code when we define a module is Lazy RouterModule.forChild:

@NgModule({
  imports: [RouterModule.forChild([
    {path: "", component: LazyComponent},
  ])],
  declarations: [LazyComponent],
})
export class LazyModule { }

But when we load in the parent module, try the below code:

@NgModule({
  declarations: [
    AppComponent,
    HelloComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    RouterModule.forRoot([
     {
         path: '',
         loadChildren: './layout/layout.module#LayoutModule',
         canActivate: [AuthGuard]
     }
    ]) <======== right way to load lazy module
  ],
  bootstrap: [AppComponent]
})
export class AppModule {
}

Note: FullPath is like './moduleFolder/lazy.module#LayoutModule'

LayoutModule is your exported Module Name

Please let me know

1 Comment

This doesn't answer his question. Where is forRoot mentioned here?
0

If a module (let's call it LazyModule) requires some parameters to be provided through forRoot and is imported inside two separate apps (let's call them A and B), we can define two modules (one in each app)

In app A:

@NgModule({
imports: [
    LazyModule.forRoot(aParamFromAppA)
]
})
export class AModule

And in app B :

@NgModule({
imports: [
    LazyModule.forRoot(anotherParamFromAppB)
]
})
export class BModule

It allows us to import both those modules lazily from their app :

loadChildren: () => import('PATH/TO/MODULE/A/AModule.module').then(m => m.AModule)
loadChildren: () => import('PATH/TO/MODULE/B/BModule.module').then(m => m.BModule)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.