Lazy-Loaded Feature Modules and Global Services in Angular 2

When you lazy-load an NgModule in Angular 2, it creates a child dependency injection context for that module.

The services that you provide in that module and all the services that are provided in any imported modules to the lazy-loaded module are newly created for that child dependency injection context.

This is a security measure due to the fact that it used to be possible in AngularJS for lazy-loaded code was able to overwrite global services.

If you have services that hold state that is interesting to the lazy-loaded modules as well you have a problem because the newly created services in the lazy-loaded module don’t have access to that state.


How to share services with lazy-loaded modules

Thankfully the Angular team is aware of that and created a solution for this. In order to avoid the re-creation of services that are imported from a SharedModule for instance, that SharedModule can’t have a provider list in its module definition.

This is possible by using conventions introduced by the Angular team: Add a static forRoot() function to your SharedModule that returns a ModuleWithProviders type. ModuleWithProviders is an interface that is provided by Angular core. This Interface expects two properties:

  1. ngModule which contains the module name that you want to add providers to and
  2. providers which contains the provider list that would normally be part of the NgModule decorator.

This SharedModule now gets added to the module imports of the root module with SharedModule.forRoot().

This means the SharedModule declaration does not have a providers list in it directly so to speak. Which means that the lazy-loaded module that imports SharedModule does not re-initialize the services that are hidden away in the forRoot() function for the child injector.

If you want dive deeper into this subject and see some example code check out this excellent article by Angular University on the topic: