What is purpose of using forRoot in NgModule?

Mantu Nigam picture Mantu Nigam · Nov 28, 2017 · Viewed 25.3k times · Source

What is the purpose of using forRoot in NgModule?

Is it same as the providers in AngularJS 1.x?

How does it play the significant role in lazy loading?

TIA.

Answer

JBoothUA picture JBoothUA · Nov 28, 2017

It has to do with singletons. Angular services are loaded onto the page 1 time (singleton) and all references point back to this 1 instance.

There is a risk that a lazy loaded module will try to create a 2nd instance of what should be a singleton, and the forRoot() method is a way to ensure that the app module / shared module / and any lazy loaded module all use the same 1 instance (the root instance).

More info copied from: Provide core singleton services module in Angular 2

The best approach is to create module with providers. Keep in mind that if your service is in shared module, you may get multiple instances of it. Best idea then is to configure module with Module.forRoot.

By convention, the forRoot static method both provides and configures services at the same time. It takes a service configuration object and returns a ModuleWithProviders.

Call forRoot only in the root application module, AppModule. Calling it in any other module, particularly in a lazy loaded module, is contrary to the intent and is likely to produce a runtime error.

Remember to import the result; don't add it to any other @NgModule list.

EDIT - FOUND SOME MORE INFORMATION ON THE ANGULAR DOCS IN REGARDS TO CODY'S QUESTION IN THE COMMENTS..

If a module provides both providers and declarations (components, directives, pipes) then loading it in a child injector such as a route, would duplicate the provider instances. The duplication of providers would cause issues as they would shadow the root instances, which are probably meant to be singletons. For this reason Angular provides a way to separate providers out of the module so that same module can be imported into the root module with providers and child modules without providers.

Create a static method forRoot() (by convention) on the module. Place the providers into the forRoot method as follows. To make this more concrete, consider the RouterModule as an example. RouterModule needs to provide the Router service, as well as the RouterOutlet directive. RouterModule has to be imported by the root application module so that the application has a Router and the application has at least one RouterOutlet. It also must be imported by the individual route components so that they can place RouterOutlet directives into their template for sub-routes.

If the RouterModule didn’t have forRoot() then each route component would instantiate a new Router instance, which would break the application as there can only be one Router. For this reason, the RouterModule has the RouterOutlet declaration so that it is available everywhere, but the Router provider is only in the forRoot(). The result is that the root application module imports RouterModule.forRoot(...) and gets a Router, whereas all route components import RouterModule which does not include the Router.

If you have a module which provides both providers and declarations, use this pattern to separate them out.