What is the purpose of providedIn with the Injectable decorator?


What is Injectable decorator?

Marks a class as available to Injector for creation.

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

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

The service itself is a class that the CLI generated and that’s decorated with @Injectable().

What exactly does providedIn do?

Determines which injectors will provide the injectable, by either associating it with an @NgModule or other InjectorType, or by specifying that this injectable should be provided in the ‘root’ injector, which will be the application-level injector in most apps.

providedIn: Type<any> | 'root' | null

providedIn: ‘root’

When you provide the service at the root level, Angular creates a single, shared instance of service and injects it 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 from the compiled app if it isn’t used.

providedIn: Module

It’s also possible to specify that a service should be provided in a particular @NgModule. For example, if you don’t want a service to be available to applications unless they import a module you’ve created, you can specify that the service should be provided in the module

import { Injectable } from '@angular/core';
import { UserModule } from './user.module';

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

This method is preferred because it enables Tree-shaking (Tree shaking is a step in a build process that removes unused code from a code base) of the service if nothing injects it.

If it’s not possible to specify in the service which module should provide it, you can also declare a provider for the service within the module:

import { NgModule } from '@angular/core';
import { UserService } from './user.service';

@NgModule({
  providers: [UserService],
})
export class UserModule {
}

I’d like to extend it by adding examples.

if you just use Injectable decorator without providedin property, like,

@Injectable()

then you would have to write service’s name in respective Module’s providers Array.

like this;

data.service.ts ↴

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

@Injectable()
export class DataService {
    constructor() {}

    // Code . . .
}

app.module.ts ↴

import { AppComponent } from './app.component';
import { DataService } from './core/data.service';

@NgModule({
    declarations: [AppComponent],
    providers: [DataService],    // ⟵ LOOK HERE WE PROVIDED IT
    imports: [...],
    bootstrap: [AppComponent],
})
export class AppModule {}

But, If you use providedIn: 'root', like this:

data.service.ts ↴

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

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

    // Code . . .
}

Then our module would look like this:

app.module.ts ↴

import { AppComponent } from './app.component';
import { DataService } from './core/data.service';

@NgModule({
    declarations: [AppComponent],
    providers: [],
    imports: [...],
    bootstrap: [AppComponent],
})
export class AppModule {}

see I didn’t add DataService in providers array this time, because it’s not needed.

Good Practices

This might come in handy, from Angular Guides

Do provide a service with the app root injector in the @Injectable decorator of the service.

Why? The Angular injector is hierarchical.

Why? When you provide the service to a root injector, that instance of the service is shared and available in every class that needs the service. This is ideal when a service is sharing methods or state.

Why? When you register a service in the @Injectable decorator of the service, optimization tools such as those used by the Angular CLI’s production builds can perform tree shaking and remove services that aren’t used by your app.

Why? This is not ideal when two different components need different instances of a service. In this scenario it would be better to provide the service at the component level that needs the new and separate instance.