39

With Angular 6, below is the preferred way to create singleton services:

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root',
})
export class UserService {
}

From Angular doc: When you provide the service at the root level, Angular creates a single, shared instance of HeroService and injects into any class that asks for it. Registering the provider in the @Injectable metadata also allows Angular to optimize an app by removing the service if it turns out not to be used after all.

Also,

providers: [
    // no need to place any providers due to the `providedIn` flag...
  ]

So, does that mean we no more need CoreModule? We can import services and other common modules directly into AppModule.

Manish Jain
  • 9,569
  • 5
  • 39
  • 44
  • 4
    Looks like a yes, it could be obsolete for me, but then where do we keep all the services ? In a root folder called 'coreServices' :) – Adrian Fâciu Jul 08 '18 at 09:51

8 Answers8

7

Well I would consider it as an alternative to creating a CoreModule, the documentation clearly states:

There are two ways to make a service a singleton in Angular: Declare root for the value of the @Injectable() providedIn property

Include the service in the AppModule or in a module that is only imported by the AppModule

I found this here Singleton Services doc

If you app has a CoreModule of pure services you could simply get rid of it(if you don't think is necessary of course), although I don't recommend it, for me I consider it more mantainable to have a CoreModule because I can easily find it in the project and tells me what services are fundamental for the app and we need only one instance from them, instead of having to open a search dialog in the IDE and look for all the services that have the providedIn: 'root' setted.

Otto Cheley
  • 552
  • 9
  • 20
  • The preferred way o provide a service in a module is to use "providedIn". This method is preferred because it enables tree-shaking of the service if nothing injects it. – Pranjal Successena Nov 11 '21 at 09:49
5

I would still keep CoreModule for single use components and Http interceptors, with the providedIn property is now the recommended way to register singleton services, just for clarity I would put all my singleton services under core/services directory

ahmedjaad
  • 683
  • 1
  • 8
  • 14
2

I think creating a core module became obsolete since a service can define itself to be registered to root via providedIn: root

The (old!) angular style guide recommended to create a core module till v6: https://v6.angular.io/guide/styleguide

But since v7 there is no recommendation anymore to create a core module. I think it is exactly for that reason (providedIn: root does the job).

spierala
  • 2,349
  • 3
  • 25
  • 50
1

That would be true if the CoreModule only contained services. However, it does include other things such as single use components.

From Angular Docs:

Do gather application-wide, single use components in the CoreModule. Import it once (in the AppModule) when the app starts and never import it anywhere else. (e.g. NavComponent and SpinnerComponent).

m4design
  • 2,112
  • 3
  • 21
  • 28
  • 6
    There still is a debate about placing components in the core module. [Documentation also state that](https://angular.io/guide/ngmodule-faq#what-kinds-of-modules-should-i-have-and-how-should-i-use-them): "Consider making CoreModule a pure services module with no declarations." – Adrian Fâciu Jul 08 '18 at 10:16
  • By single-use component, you mean a component that is used only in your AppComponent template, and nowhere else, right? – crush Jan 22 '19 at 16:08
1

And what about interceptors and guards? This things can be global I guess. I agree with your consideration about CoreModule doesn't have declarations and only pure services, but I think Guards and Interceptors should be considerate too.

  • Totally agree with you: CoreModule is the only appropriate Module for Guards and Interceptors, since they only need to be provided once. – dave0688 Sep 21 '18 at 07:51
  • 4
    @dave0688 But you can use the `providedIn: 'root'` on guards and interceptors too. This also makes them tree-shakable, whereas adding them to the CoreModule negates them being tree-shakable. That is why Angular recommends `providedIn: 'root'` – crush Jan 22 '19 at 16:06
1

When Angular engine starts initiating a component, and you have declared services in your constructor, angular tries to pass the instances of the declared services to the component. So angular should somehow know where can be taken instances, there is a point where providers array comes.

When you declare needed services without providedin: core pair, we create non singleton instance of the service. which means that, when angular destroys component, services declared in the component will be destroyed too.

As mentioned before, there are two ways to declare application level singleton services: 1. declare them into providers of related module; 2. declare them into providers of a component with providedIn: core pair.

also interesting note about @Injectable decorator. this is only required when service injects another service. for example if you inject http service in your service, you have to add @Injecrable decorator.

this is how dependency injection works.

0

provideIn: root this could be useful in those scenarios where you have multi-application projects. In such kind of scenarios, you have an angular workspace with multiple projects inside it.

And, you would never want your project to have some kind of dependencies on the workspace's core module as it won't allow you to run your project independently.

In such a case, you keep your services in the library and use providedIn: 'root' for making them singleton.

Rajat Badjatya
  • 760
  • 6
  • 13
0
  • providedIn: 'root' is the declarative way
  • core module is the imperative way

If you need to conditionally inject providers, it is easy to do it within a module, and the core module is the one importing every mandatory service for your app. This is useful for instance to import testing or production services depending on an environment variable.

If you do have only one version for your service, then providedIn: 'root' is a good to go.

Flavien Volken
  • 19,196
  • 12
  • 100
  • 133