Перейти к содержанию

NgModules

📅 30.09.2026

Для всего нового кода команда Angular рекомендует автономные компоненты вместо NgModule. Это руководство нужно, чтобы понимать уже написанный код на @NgModule.

NgModule — класс, помеченный декоратором @NgModule. Декоратор принимает метаданные: по ним Angular компилирует шаблоны компонентов и настраивает инъекцию зависимостей.

1
2
3
4
5
6
import {NgModule} from '@angular/core';

@NgModule({
  // Metadata goes here
})
export class CustomMenuModule {}

У NgModule две главные задачи:

  • объявляет компоненты, директивы и пайпы, которые принадлежат NgModule;
  • добавляет провайдеры в инжектор для компонентов, директив и пайпов, которые импортируют этот NgModule.

Объявления

Свойство declarations метаданных @NgModule перечисляет компоненты, директивы и пайпы этого NgModule.

1
2
3
4
5
6
@NgModule({
  /* ... */
  // CustomMenu and CustomMenuItem are components.
  declarations: [CustomMenu, CustomMenuItem],
})
export class CustomMenuModule {}

В примере выше компоненты CustomMenu и CustomMenuItem принадлежат CustomMenuModule.

Кроме того, declarations принимает массивы компонентов, директив и пайпов. Внутри таких массивов могут быть другие массивы.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
const MENU_COMPONENTS = [CustomMenu, CustomMenuItem];
const WIDGETS = [MENU_COMPONENTS, CustomSlider];

@NgModule({
  /* ... */
  // This NgModule declares all of CustomMenu, CustomMenuItem,
  // CustomSlider, and CustomCheckbox.
  declarations: [WIDGETS, CustomCheckbox],
})
export class CustomMenuModule {}

Если компонент, директива или пайп объявлены больше чем в одном NgModule, Angular сообщает об ошибке.

Чтобы объявить компонент, директиву или пайп в NgModule, их нужно явно пометить standalone: false.

1
2
3
4
5
6
7
8
@Component({
  // Mark this component as `standalone: false` so that it can be declared in an NgModule.
  standalone: false,
  /* ... */
})
export class CustomMenu {
  /* ... */
}

Импорты

Компонент, объявленный в NgModule, может зависеть от других компонентов, директив и пайпов. Такие зависимости добавляют в свойство imports метаданных @NgModule.

1
2
3
4
5
6
7
@NgModule({
  /* ... */
  // CustomMenu and CustomMenuItem depend on the PopupTrigger and SelectorIndicator components.
  imports: [PopupTrigger, SelectionIndicator],
  declarations: [CustomMenu, CustomMenuItem],
})
export class CustomMenuModule {}

В массив imports входят другие NgModule, а также автономные компоненты, директивы и пайпы.

Экспорты

NgModule может экспортировать объявленные компоненты, директивы и пайпы. Тогда они доступны другим компонентам и NgModule.

1
2
3
4
5
6
7
8
9
@NgModule({
  imports: [PopupTrigger, SelectionIndicator],
  declarations: [CustomMenu, CustomMenuItem],

  // Make CustomMenu and CustomMenuItem available to
  // components and NgModules that import CustomMenuModule.
  exports: [CustomMenu, CustomMenuItem],
})
export class CustomMenuModule {}

Свойство exports не ограничено собственными объявлениями. NgModule может экспортировать и те компоненты, директивы, пайпы и NgModule, которые сам импортирует.

1
2
3
4
5
6
7
8
@NgModule({
  imports: [PopupTrigger, SelectionIndicator],
  declarations: [CustomMenu, CustomMenuItem],

  // Also make PopupTrigger available to any component or NgModule that imports CustomMenuModule.
  exports: [CustomMenu, CustomMenuItem, PopupTrigger],
})
export class CustomMenuModule {}

Провайдеры NgModule

Про инъекцию зависимостей и провайдеры — в руководстве по инъекции зависимостей.

NgModule задаёт providers для внедряемых зависимостей. Эти провайдеры доступны:

  • любому автономному компоненту, директиве и пайпу, которые импортируют этот NgModule;
  • объявлениям declarations и провайдерам providers любого другого NgModule, который импортирует этот.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
@NgModule({
  imports: [PopupTrigger, SelectionIndicator],
  declarations: [CustomMenu, CustomMenuItem],

  // Provide the OverlayManager service
  providers: [OverlayManager],
  /* ... */
})
export class CustomMenuModule {}

@NgModule({
  imports: [CustomMenuModule],
  declarations: [UserProfile],
  providers: [UserDataClient],
})
export class UserProfileModule {}

В примере выше:

  • CustomMenuModule предоставляет сервис OverlayManager;
  • компоненты CustomMenu и CustomMenuItem могут внедрить OverlayManager, потому что объявлены в CustomMenuModule;
  • UserProfile может внедрить OverlayManager, потому что его NgModule импортирует CustomMenuModule;
  • UserDataClient может внедрить OverlayManager, потому что его NgModule импортирует CustomMenuModule.

Паттерн forRoot и forChild

У некоторых NgModule есть статический метод forRoot. Он принимает конфигурацию и возвращает массив провайдеров. Имя forRoot — соглашение: эти провайдеры добавляют только в корень приложения, во время запуска.

Такие провайдеры загружаются сразу и увеличивают размер JavaScript первой загрузки страницы.

1
2
3
bootstrapApplication(MyApplicationRoot, {
  providers: [CustomMenuModule.forRoot(/* some config */)],
});

Статический метод forChild у части NgModule означает другое: провайдеры предназначены компонентам внутри иерархии приложения.

1
2
3
4
5
6
7
@Component({
  /* ... */
  providers: [CustomMenuModule.forChild(/* some config */)],
})
export class UserProfile {
  /* ... */
}

Запуск приложения

Для нового кода команда Angular рекомендует bootstrapApplication вместо bootstrapModule. Здесь — как устроены приложения, которые по-прежнему запускают через @NgModule.

Декоратор @NgModule принимает необязательный массив bootstrap с одним или несколькими компонентами.

Приложение Angular запускают методом bootstrapModule у platformBrowser или platformServer. При вызове функция находит на странице элементы, чей CSS-селектор совпадает с указанными компонентами, и отрисовывает эти компоненты.

1
2
3
4
5
6
7
8
import {platformBrowser} from '@angular/platform-browser';

@NgModule({
  bootstrap: [MyApplication],
})
export class MyApplicationModule {}

platformBrowser().bootstrapModule(MyApplicationModule);

Компоненты из bootstrap автоматически входят в объявления NgModule.

Когда приложение запускают из NgModule, собранные providers этого модуля и все providers из его imports загружаются сразу и доступны для инъекции во всём приложении.


Источник: https://angular.dev/guide/ngmodules/overview

Комментарии