Skip to content

Angular Modules

Before standalone components, every Angular application organized its components, directives, and pipes into NgModules. This lesson explains how NgModules work, since many existing codebases still use them.

What Is an NgModule?

An NgModule is a class decorated with @NgModule that groups related components, directives, and pipes together, declares what they need (imports), and optionally makes some of them available to other modules (exports).

Every classic Angular application has at least a root AppModule, and often several feature modules organizing related functionality into logical, sometimes lazily-loaded, chunks.

@NgModule({
  declarations: [UserListComponent, UserCardComponent],
  imports: [CommonModule, RouterModule],
  exports: [UserListComponent],
})
export class UserModule {}

declarations lists this module's own components/directives/pipes; exports makes UserListComponent usable by any module that imports UserModule.

The @NgModule Decorator

@NgModule({
  declarations: [Comp1, Directive1, Pipe1],
  imports: [OtherModule1, OtherModule2],
  exports: [Comp1],
  providers: [SomeService],
  bootstrap: [RootComponent], // only on the root module
})
export class FeatureModule {}
  • declarations lists non-standalone components, directives, and pipes that belong to this module.
  • imports brings in other modules whose exported declarations/functionality this module needs.
  • exports makes some of this module's declarations available to modules that import it.
  • bootstrap is only used on the root module, identifying which component starts the application.

NgModule Cheatsheet

The metadata options you'll see on classic NgModule-based Angular code.

Property Purpose
declarations Components/directives/pipes owned by this module
imports Other modules this module depends on
exports Declarations made available to importing modules
providers Services registered by this module
bootstrap The root component to bootstrap (root module only)
CommonModule Provides *ngIf, *ngFor, and other common directives
RouterModule Provides router-outlet, routerLink, and routing config

Root Module vs Feature Modules

The root module (AppModule) bootstraps the whole application and typically imports feature modules, each responsible for a cohesive slice of functionality, like an OrdersModule or a SettingsModule.

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

NgModules vs Standalone Components

Standalone components (the modern default since Angular 17) remove the need for NgModule boilerplate entirely, each component declares its own dependencies via its own imports array. Existing NgModule-based codebases remain fully supported and can adopt standalone components incrementally.

NgModule-based Standalone
Declaring a component Listed in a module's declarations No module needed at all
Bringing in dependencies Module-level imports Per-component imports
Boilerplate More (module files per feature) Less

Migrating From NgModules

The Angular CLI includes a schematic that automatically converts an NgModule-based project to standalone components, ng generate @angular/core:standalone, useful for gradually modernizing an existing codebase rather than a risky big-bang rewrite.

Common Mistakes

  • Declaring the same component in more than one module's declarations array, which Angular does not allow.
  • Forgetting to export a component that other modules need to use in their templates.
  • Mixing standalone components into an NgModule's declarations array; standalone components must be imported, not declared.
  • Treating NgModules as strictly required knowledge for new projects, when standalone components are now the recommended default.

Key Takeaways

  • @NgModule groups components, directives, and pipes together via declarations, imports, and exports.
  • A root module bootstraps the application; feature modules organize related functionality.
  • Standalone components replace most NgModule boilerplate in modern Angular, but NgModules remain fully supported.
  • The Angular CLI provides a schematic to migrate existing NgModule-based code to standalone components.

Pro Tip

For new projects, skip NgModules entirely and start with standalone components; only reach for @NgModule knowledge when maintaining or gradually migrating an existing legacy codebase.