'Are Angular Service Modules still required?

In the angular docs, it lists the types of feature modules that one can implement. One of those being a service module.

https://angular.io/guide/module-types

In earlier versions of Angular, you would create your service and list it in the providers array of the service NgModule. This NgModule would then be imported by the consuming application where the service will be provided in the application root injector.

Injectable()
export class MyService {}

NgModule({
    providers: [MyService]
})
export class MyServicesModule {}

NgModule({
    imports: [MyServicesModule]
})
export class AppModule {}

The newest Angular recommendation is to use the Injectable annotation, where you no longer need to list it in the providers definition.

Injectable({ providedIn: 'root'})
export class MyService {}

Therefore is there any point in creating a service module? Do you just create the services you want provided in the root injector using the above annotation and just import the service class directly and inject accoridngly?



Solution 1:[1]

A service module would be required if you are using lazy loaded modules which have specific services only provided inside that module.

You can't provide a service into the same module where components of that module get the service injected.

So assume you have a MyLazyFeatureModule

@NgModule({
  imports:      [ ],
  providers:    [ ],
  declarations: [ MyFeatureComponent ],
  exports:      [ ],
})
export class MyLazyFeatureModule { }

and you have a service which contains logic only for your feature, then you cannot do the following:

Injectable({ providedIn: MyLazyFeatureModule})
export class MyFeatureService {}

You would get a cycle!

To resolve the issue you need to create a specific service module and import that module into the feature module:

@NgModule({
  imports:      [ ],
  providers:    [ ],
  declarations: [ ],
  exports:      [ ],
})
export class MyLazyFeatureServiceModule { }
Injectable({ providedIn: MyFeatureServiceModule})
export class MyFeatureService {}
@NgModule({
  imports:      [ MyLazyFeatureServiceModule ],
  providers:    [ ],
  declarations: [ MyFeatureComponent ],
  exports:      [ ],
})
export class MyLazyFeatureModule { }

Please have a look at this article (three shakable providers why, how and cycles by Manfred Steyer which explains the details of why there is a cycle quite in depth.

Besides of that use case you probably would not need a service module if you only have services provided in root. You could create one to actually have all services in one place. But maybe a core module would do for that as well. That's up to you.

Solution 2:[2]

A singleton service is a service that providedIn: 'root' to take advantage of tree-shaking.

The location of a service file:

  • in a feature module's services folder, you could put a.service.ts file here
  • for a service that doesn't seem to belong to a specific feature module (eg. a logger service used by many modules), you may organize the service into a core folder without a core.module.ts. See angular doc on coding style guide.

However, depending on the case, if you are using ngrx store or similar lib, you may want a CoreModule or some ServiceModule(s) to import the files (ngrx module) away there. See angular v6 doc on coding style guide.

P.S. For sharing things app-wide, a SharedModule is considered for pipes, directives, and components, but not for services. shared.module.ts is likely to have no providers property in its @NgModule decorator. See angular doc on SharedModule.

The underlying reason for this naming convention 1 is that the root injector is there for all singleton services (working well for both eager modules and lazy loaded modules), so that you usually don't want to create another injector (unless you know what you're doing, such as the forRoot pattern 2 eg<- btw please remember that such a hassle is avoided if you have already let all services providedIn: 'root' ).

To sum up, the angular doc recommend making all services singleton and tree-shakable 3 4 ; the services fit into 3 places: a feature module's services folder OR a core module / service module, especially when using ngrx OR a core folder just for holding services organized and tidy.


related docs and references

https://angular.io/guide/singleton-services

https://angular.io/guide/providers

https://angular.io/guide/router

https://angular.io/guide/lazy-loading-ngmodules

https://v6.angular.io/guide/styleguide CoreModule 1 2 3

https://angular.io/guide/styleguide

https://angular.io/guide/module-types

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2