← Back to Articles         
Standalone vs Traditional NgModule Angular

Standalone vs Traditional NgModule Angular

Published on 29 Sep 2026     7 min read Angular
Angular Fundamentals

1. What is a standalone component in Angular?

A standalone component works without being declared in an NgModule. It can directly import the components, directives, pipes, or modules it needs.

@Component({ standalone: true, imports: [CommonModule] })
export class Home {}

2. How were Angular applications structured before standalone components?

Earlier Angular applications were organized using NgModules. Components, directives, pipes, services, and imported modules were typically grouped inside modules such as AppModule.

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

3. What is NgModule?

NgModule is an Angular decorator used to group and configure related Angular functionality. Traditionally, it registered components, directives, pipes, modules, and providers.

@NgModule({ declarations: [HomeComponent], imports: [CommonModule] })
export class AppModule {}

4. What was the purpose of AppModule in traditional Angular applications?

AppModule was normally the root module of an Angular application. It configured the application's root components, dependencies, and modules.

@NgModule({ bootstrap: [AppComponent] })
export class AppModule {}

5. What was the purpose of the declarations array in NgModule?

declarations registered the components, directives, and pipes owned by that module. A non-standalone component had to belong to an NgModule.

declarations: [AppComponent, HomeComponent, HighlightDirective]

6. What was the purpose of the imports array in NgModule?

imports made functionality exported by other NgModules available to the current module.

imports: [BrowserModule, FormsModule, AppRoutingModule]

7. What was the purpose of the providers array in NgModule?

providers registered services or dependency-injection providers with Angular's injector.

providers: [ProductService]

Modern services commonly use:

@Injectable({ providedIn: 'root' })

8. What was the purpose of the bootstrap array in NgModule?

The bootstrap array specified the root component Angular should start when bootstrapping that module.

@NgModule({ bootstrap: [AppComponent] })
export class AppModule {}

9. How were components registered before standalone components?

Components were registered by adding them to an NgModule's declarations array.

@NgModule({
  declarations: [AppComponent, ProductComponent]
})

10. How were directives and pipes registered before standalone APIs?

Custom directives and pipes were also placed inside an NgModule's declarations array.

declarations: [HighlightDirective, CurrencyFormatPipe]

They could then be exported for use by other modules.

11. How were services provided before standalone APIs?

Services could be registered in an NgModule's providers array. Later Angular versions commonly used providedIn: 'root' instead.

@NgModule({ providers: [ProductService] })

or

@Injectable({ providedIn: 'root' })

12. How was routing configured using AppRoutingModule?

A separate AppRoutingModule commonly called RouterModule.forRoot(routes) and exported RouterModule.

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule {}

13. How was HttpClientModule configured before standalone APIs?

HttpClientModule was imported into an NgModule, usually AppModule, to make HttpClient available through dependency injection.

@NgModule({
  imports: [BrowserModule, HttpClientModule]
})

14. How was BrowserModule used in module-based Angular?

BrowserModule was imported by the root browser application module. It provides infrastructure required to run Angular in a browser.

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

15. How was FormsModule imported before standalone components?

For template-driven forms, FormsModule was imported into the NgModule containing those components.

@NgModule({
  imports: [FormsModule]
})

This enabled features such as [(ngModel)].

16. How was ReactiveFormsModule imported before standalone components?

For reactive forms, ReactiveFormsModule was added to the module's imports array.

@NgModule({
  imports: [ReactiveFormsModule]
})

This enabled FormGroup, FormControl, formGroup, etc.

17. What replaced AppModule in a standalone Angular application?

Standalone applications don't require a root AppModule. The root component is bootstrapped directly, while application-level providers are commonly configured using ApplicationConfig.

bootstrapApplication(App, appConfig);

18. What replaced platformBrowserDynamic().bootstrapModule(AppModule)?

Modern standalone Angular uses bootstrapApplication().

Old:

platformBrowserDynamic().bootstrapModule(AppModule);

New: bootstrapApplication(App, appConfig);

19. What is bootstrapApplication()?

bootstrapApplication() starts a standalone Angular application using a standalone root component.

bootstrapApplication(App, appConfig)
  .catch(err => console.error(err));

It removes the requirement for a root AppModule.

20. What is ApplicationConfig?

ApplicationConfig represents application-level configuration and providers for a standalone application.

export const appConfig: ApplicationConfig = {
  providers: [provideRouter(routes)]
};

21. What is app.config.ts?

app.config.ts commonly contains the application's global provider configuration.

export const appConfig: ApplicationConfig = {
  providers: [provideRouter(routes), provideHttpClient()]
};

It is commonly passed to bootstrapApplication().

22. What is app.routes.ts?

app.routes.ts commonly contains the application's route definitions.

export const routes: Routes = [
  { path: 'home', component: Home }
];

These routes are registered using provideRouter(routes).

23. What does standalone: true mean?

standalone: true tells Angular that the component, directive, or pipe does not need to be declared in an NgModule.

@Component({
  standalone: true
})
export class Product {}

24. How are dependencies imported directly into standalone components?

Standalone components have their own imports array. Required components, directives, pipes, and compatible NgModules can be imported directly.

@Component({
  imports: [CommonModule, FormsModule]
})

25. What is the difference between NgModule imports and standalone component imports?

NgModule.imports makes dependencies available to declarations within that module. A standalone component's imports specifies what that component's template directly depends on.

// Standalone
@Component({ imports: [FormsModule] })

26. What replaced RouterModule.forRoot() in standalone Angular?

For standalone application configuration, RouterModule.forRoot(routes) is generally replaced by provideRouter(routes).

providers: [
  provideRouter(routes)
]

Routes can be stored separately in app.routes.ts.

27. What is provideRouter()?

provideRouter() registers Angular Router services and the application's route configuration using standalone provider APIs.

export const appConfig: ApplicationConfig = {
  providers: [provideRouter(routes)]
};

28. What replaced HttpClientModule in modern standalone configuration?

Modern standalone applications normally use provideHttpClient() instead of importing HttpClientModule at the application root.

providers: [
  provideHttpClient()
]

Components/services can then inject HttpClient.

29. What is provideHttpClient()?

provideHttpClient() configures Angular's HTTP client services using the provider-based standalone API.

export const appConfig: ApplicationConfig = {
  providers: [provideHttpClient()]
};

Then use inject(HttpClient) or constructor injection.

30. How are HTTP interceptors configured in standalone Angular?

Functional interceptors can be registered using provideHttpClient() with withInterceptors().

provideHttpClient(
  withInterceptors([authInterceptor])
)

An interceptor can modify outgoing requests or incoming responses.

31. How are route guards configured in standalone Angular?

Guards are attached directly to route definitions. Modern Angular commonly uses functional guards.

export const routes: Routes = [
  { path: 'admin', component: Admin, canActivate: [authGuard] }
];

32. Can standalone components use existing NgModules?

Yes. Standalone components can import existing NgModules, which is useful when working with older Angular libraries or during migration.

@Component({
  standalone: true,
  imports: [FormsModule]
})

33. Can NgModule-based components use standalone components?

Yes. An NgModule can import a standalone component instead of declaring it.

@NgModule({
  imports: [MyStandaloneComponent]
})
export class FeatureModule {}

Do not put the standalone component in declarations.

34. Can standalone and NgModule approaches coexist?

Yes. Angular supports gradual migration, so standalone components and traditional NgModules can coexist in the same application.

@Component({
  standalone: true,
  imports: [LegacyModule]
})

This is useful for large existing applications.

35. How do you migrate an NgModule-based Angular application to standalone?

Migration is normally gradual: convert declarations to standalone, move dependencies to component imports, replace module-level configuration with provider APIs, then bootstrap directly.

bootstrapApplication(App, {
  providers: [provideRouter(routes), provideHttpClient()]
});

Angular CLI migrations can also assist with standalone conversion.

36. What are the advantages of standalone Angular?

Standalone APIs reduce NgModule boilerplate and make dependencies more explicit. They simplify application structure and work naturally with modern Angular APIs.

@Component({
  imports: [RouterLink, FormsModule]
})

The component clearly shows its template dependencies.

37. What are the disadvantages or migration challenges of standalone Angular?

Existing large applications may contain many NgModules, third-party module APIs, and module-level providers that require careful migration. Teams familiar with NgModules also need to adjust their project structure.

// Legacy code may still depend on:
@NgModule({ imports: [LegacyLibraryModule] })

38. Standalone vs NgModule — what is the difference?

NgModule approach Standalone approach
Components declared in modules Components don't require declaration
Uses AppModule Uses bootstrapApplication()
RouterModule.forRoot() provideRouter()
Module-centric Component/provider-centric

Example: @Component({ standalone: true, imports: [RouterLink] })

39. Is NgModule deprecated?

No. NgModule is not deprecated. Angular supports NgModule-based applications, but standalone APIs are the recommended direction for new Angular development.

@NgModule({
  declarations: [LegacyComponent]
})
export class LegacyModule {}

So existing NgModule applications do not have to be immediately rewritten.

40. When maintaining an older Angular project, why is understanding NgModule still important?

Many production Angular applications and libraries were built around NgModule. You need to understand declarations, imports, providers, exports, and module-based routing to maintain or migrate them.

@NgModule({
  declarations: [ProductComponent],
  imports: [CommonModule]
})
export class ProductModule {}

Understanding both NgModule and standalone Angular is therefore important for Angular interviews and real-world maintenance.

← Back to Articles