Angular Modules

작성자

카테고리:

← 피드로
DEV Community · atilla baspinar · 2026-06-30 개발(SW)

1. What is an NgModule

An NgModule groups related components, directives, and pipes together. It was the primary way to structure Angular apps before standalone components arrived in Angular 14.

NgModules are not deprecated — they are still fully supported in Angular 21. Only platformBrowserDynamic (the old bootstrap function) was deprecated. The recommended path for new projects is standalone components, but NgModules remain valid for existing codebases.

2. NgModule Anatomy

The @NgModule decorator accepts five main properties:

Property Purpose declarations Non-standalone components, directives, and pipes owned by this module imports Other NgModules or standalone components/pipes this module needs exports What this module exposes to other modules that import it providers Services to register (prefer providedIn: 'root' on the service itself) bootstrap The root component Angular renders on startup — root module only
@NgModule({
  declarations: [App],
  bootstrap: [App],
  imports: [BrowserModule, CommonModule, Tasks, NewTask, Task, User, Header, RouterOutlet],
})
export class AppModule {}

Enter fullscreen mode Exit fullscreen mode

3. declarations vs imports

This is the most common source of confusion when mixing modules with standalone components.

  • declarations — only for non-standalone components (standalone: false). They are private to this module unless explicitly exported.
  • imports — for other NgModules and for standalone components, directives, and pipes (the default since Angular 17).

Putting a standalone component in declarations causes a compile error. Putting a non-standalone component in imports also causes an error.

// non-standalone component — belongs in declarations
@Component({
  standalone: false,
  selector: 'app-root',
  templateUrl: './app.html',
  styleUrl: './app.css',
})
export class App {}

Enter fullscreen mode Exit fullscreen mode

// standalone component (Angular 17+ default) — belongs in imports, not declarations
@Component({
  selector: 'app-header',
  templateUrl: './header.html',
})
export class Header {}

Enter fullscreen mode Exit fullscreen mode

@NgModule({
  declarations: [App],                          // non-standalone
  imports: [BrowserModule, Header, RouterOutlet], // standalone components go here
  bootstrap: [App],
})
export class AppModule {}

Enter fullscreen mode Exit fullscreen mode

A non-standalone component also cannot have an imports array in @Component — it delegates all imports to its module.

4. BrowserModule vs CommonModule

Module Use when BrowserModule Root module only — sets up the browser platform, includes CommonModule internally CommonModule Feature modules — provides NgIf, NgFor, NgClass, pipes, etc.

Never import BrowserModule in a feature module — import CommonModule instead. Importing BrowserModule twice throws a runtime error.

5. Bootstrapping with NgModule

Use platformBrowser().bootstrapModule() from @angular/platform-browser. The older platformBrowserDynamic from @angular/platform-browser-dynamic was deprecated in Angular 21.

// main.ts
import { platformBrowser } from '@angular/platform-browser';
import { AppModule } from './app/app.module';

platformBrowser().bootstrapModule(AppModule)
  .catch((err: unknown) => console.error(err));

Enter fullscreen mode Exit fullscreen mode

6. Feature Modules

Feature modules group a slice of the app (e.g. tasks, users) to keep AppModule small. They export only what the rest of the app needs.

// tasks/tasks.module.ts
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { TasksComponent } from './tasks.component';

@NgModule({
  declarations: [TasksComponent],
  imports: [CommonModule],
  exports: [TasksComponent],
})
export class TasksModule {}

Enter fullscreen mode Exit fullscreen mode

// app.module.ts
@NgModule({
  declarations: [App],
  imports: [BrowserModule, TasksModule],
  bootstrap: [App],
})
export class AppModule {}

Enter fullscreen mode Exit fullscreen mode

7. Lazy-Loaded Feature Modules

Lazy loading defers loading a module’s bundle until the user navigates to its route. Configure it with loadChildren in the router:

// app.routes.ts
export const routes: Routes = [
  {
    path: 'tasks',
    loadChildren: () =>
      import('./tasks/tasks.module').then((m) => m.TasksModule),
  },
];

Enter fullscreen mode Exit fullscreen mode

// tasks/tasks.module.ts — use forChild, not forRoot
@NgModule({
  declarations: [TasksComponent],
  imports: [
    CommonModule,
    RouterModule.forChild([{ path: '', component: TasksComponent }]),
  ],
})
export class TasksModule {}

Enter fullscreen mode Exit fullscreen mode

The root module uses RouterModule.forRoot(routes). Feature modules use RouterModule.forChild(routes).

8. NgModule vs Standalone

NgModule Standalone Grouping Explicit module files No module needed Sharing Export from module, import the module Import the component directly Lazy loading loadChildren loadComponent Recommended for new projects No Yes Deprecated No —

NgModules are still valid and fully supported. Understanding them is essential for working with existing Angular codebases.

원문에서 계속 ↗

코멘트

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다