Difference between forRoot and forChild?
In Angular, `forRoot` and `forChild` are static methods commonly found on modules that provide routing or services. They are crucial for configuring modules that might be imported multiple times across different parts of an application, ensuring proper dependency injection and preventing redundant service instances.
Purpose
Both methods are designed to help Angular's dependency injection system manage providers efficiently, especially when dealing with feature modules and lazy loading. They prevent shared services from being instantiated multiple times, which can lead to unexpected behavior or increased memory consumption.
forRoot()
The forRoot() method should be called only once, typically in the root AppModule. Its primary purpose is to configure providers that should be singletons across the entire application. When forRoot() is called, it returns a ModuleWithProviders object containing the module itself and the providers that need to be registered at the root injector level. This ensures that services provided by forRoot() are instantiated only once and shared globally.
import { NgModule, ModuleWithProviders } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
const routes: Routes = [
// application-wide routes
];
@NgModule({})
export class AppRoutingModule {
static forRoot(routes: Routes): ModuleWithProviders<AppRoutingModule> {
return {
ngModule: AppRoutingModule,
providers: [
{ provide: 'APP_CONFIG', useValue: { apiEndpoint: '/api' } }
]
};
}
}
Usage in AppModule
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
AppRoutingModule.forRoot([
{ path: '', redirectTo: 'home', pathMatch: 'full' }
]) // Only call forRoot once in the root module
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
forChild()
The forChild() method is intended for feature modules that are typically lazy-loaded. When forChild() is called, it also returns a ModuleWithProviders object, but it usually registers routes or providers that are specific to that feature module and its injector. It does not re-register global singleton services; instead, it registers providers in the injector of the feature module itself. This is particularly useful for routing, where each lazy-loaded module defines its own child routes without interfering with the root application routes or other feature module routes.
import { NgModule, ModuleWithProviders } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
const featureRoutes: Routes = [
{ path: '', component: FeatureComponent },
{ path: 'detail/:id', component: FeatureDetailComponent }
];
@NgModule({})
export class FeatureRoutingModule {
static forChild(routes: Routes): ModuleWithProviders<FeatureRoutingModule> {
return {
ngModule: FeatureRoutingModule,
providers: [
// Providers specific to this feature module
]
};
}
}
Usage in Feature Module
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FeatureRoutingModule } from './feature-routing.module';
import { FeatureComponent } from './feature.component';
@NgModule({
declarations: [
FeatureComponent
],
imports: [
CommonModule,
FeatureRoutingModule.forChild([
{ path: '', component: FeatureComponent }
]) // Call forChild in feature modules
]
})
export class FeatureModule { }
Key Differences
| Aspect | forRoot() | forChild() |
|---|---|---|
| Usage Location | Only in the root `AppModule` | In feature modules (often lazy-loaded) |
| Provider Scope | Registers providers as singletons in the root injector (application-wide) | Registers providers in the feature module's own injector, potentially creating new instances for each lazy-loaded module |
| Purpose | Global configuration, root routes, core services (e.g., AuthGuard, HttpClientModule) | Feature-specific configuration, child routes, services local to a feature |
| Instantiations | Ensures services are instantiated once | Allows services/components to be instantiated multiple times if the feature module is loaded multiple times (e.g., if imported eagerly in different modules, though rare for routing) |
When to use which?
Use forRoot() when:
- You are defining application-wide services or configurations that should only have a single instance (singleton) throughout the application.
- You are configuring the main application routes in your
AppRoutingModule. - You want to provide a module with services that depend on other global services.
Use forChild() when:
- You are defining routes for a feature module that will be lazy-loaded.
- You are providing services that are only relevant to a specific feature module and should not be singletons across the entire application (though often, feature modules don't provide services via
forChild()for this reason, but rather directly inprovidersarray if not root-level). - You want to avoid re-registering singleton providers that
forRoot()already handles.