How to provide a service in Angular root module
Providing services in Angular root module creates application-wide singleton instances available throughout the entire application, ensuring consistent data sharing and service behavior. As the creator of CoreUI, a widely used open-source UI library, I’ve configured root-level services in thousands of Angular applications for authentication, data management, and shared utilities. From my expertise, the most effective approach is using providedIn: ‘root’ in the service decorator or configuring providers in the root module. This method provides optimal service instantiation with tree-shaking benefits and centralized service management.
Use providedIn: ‘root’ in service decorator or configure providers in root module for application-wide singleton services.
// Method 1: Using providedIn: 'root' (Recommended)
import { Injectable } from '@angular/core'
import { BehaviorSubject } from 'rxjs'
@Injectable({
providedIn: 'root'
})
export class UserService {
private userSubject = new BehaviorSubject(null)
user$ = this.userSubject.asObservable()
setUser(user: any) {
this.userSubject.next(user)
}
getUser() {
return this.userSubject.value
}
}
// Method 2: Using providers array in app.module.ts
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { AppComponent } from './app.component'
import { UserService } from './services/user.service'
@NgModule({
declarations: [AppComponent],
imports: [BrowserModule],
providers: [
UserService,
// Or with specific configuration
{
provide: UserService,
useClass: UserService
}
],
bootstrap: [AppComponent]
})
export class AppModule {}
// Usage in any component
import { Component } from '@angular/core'
import { UserService } from './services/user.service'
@Component({
selector: 'app-dashboard',
template: '<div>User: {{ user?.name }}</div>'
})
export class DashboardComponent {
user: any
constructor(private userService: UserService) {
this.userService.user$.subscribe(user => {
this.user = user
})
}
}
The providedIn: ‘root’ approach is preferred as it enables tree-shaking and lazy loading optimizations. Services provided in root module become singleton instances shared across the entire application. Both methods ensure the same service instance is injected wherever the service is requested throughout the application.
Best Practice Note:
This is the same root service configuration we use in CoreUI Angular applications for authentication, theme management, and global state services.