Что такое модули в Angular?
Модули в Angular — это логические контейнеры, которые группируют компоненты, директивы, пайпы и сервисы, объединяя их в функциональные блоки. Каждый Angular-приложение как минимум состоит из одного модуля — AppModule. Модули оформляются как классы с декоратором @NgModule, который сообщает Angular, какие элементы входят в модуль, что следует экспортировать и какие зависимости подключать.
Модули позволяют:
-
Разделять код на независимые блоки;
-
Реализовать lazy loading;
-
Повторно использовать функциональность;
-
Изолировать зависимости;
-
Упростить масштабирование и поддержку приложения.
1. Синтаксис NgModule
Модуль — это класс, помеченный декоратором @NgModule.
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { UserComponent } from './user.component';
@NgModule({
declarations: \[UserComponent\],
imports: \[CommonModule\],
exports: \[UserComponent\]
})
export class UserModule {}
2. Основные свойства @NgModule
-
declarations: Компоненты, директивы и пайпы, принадлежащие модулю.
-
imports: Другие модули, чьи публичные элементы (через exports) нужны в этом модуле.
-
exports: Элементы, которые можно использовать в других модулях, импортирующих текущий.
-
providers: Сервисы и другие зависимости, создаваемые для DI.
-
bootstrap: Компонент, с которого начинается загрузка приложения (используется только в корневом модуле).
Пример:
@NgModule({
declarations: \[AppComponent\],
imports: \[BrowserModule\],
providers: \[\],
bootstrap: \[AppComponent\]
})
export class AppModule {}
3. Типы модулей в приложении
3.1. Корневой модуль (AppModule)
-
Обязательный;
-
Запускается первым;
-
Содержит bootstrap — корневой компонент.
Файл: app.module.ts
@NgModule({
declarations: \[AppComponent\],
imports: \[BrowserModule, AppRoutingModule\],
bootstrap: \[AppComponent\]
})
export class AppModule {}
3.2. Feature-модули
-
Представляют функциональные блоки (например, UserModule, DashboardModule);
-
Могут подключаться напрямую или через lazy loading;
-
Обычно содержат свои компоненты, роутинг, сервисы.
@NgModule({
declarations: \[UserProfileComponent\],
imports: \[CommonModule\],
})
export class UserModule {}
3.3. Shared-модуль (SharedModule)
-
Хранит общие компоненты, директивы и пайпы, которые используются во многих местах;
-
Импортируется в другие модули, но сам не должен импортировать CoreModule.
@NgModule({
declarations: \[ButtonComponent, CapitalizePipe\],
exports: \[ButtonComponent, CapitalizePipe\],
imports: \[CommonModule\]
})
export class SharedModule {}
3.4. Core-модуль (CoreModule)
-
Используется для глобальных singleton-сервисов (auth, API, interceptors);
-
Импортируется только в AppModule;
-
Может реализовать forRoot()-паттерн для управления синглтонами.
@NgModule({
providers: \[AuthService, LoggerService\],
imports: \[CommonModule\]
})
export class CoreModule {}
4. CommonModule vs BrowserModule
-
BrowserModule используется только в AppModule.
-
CommonModule используется во всех остальных модулях (даёт директивы вроде *ngIf, *ngFor).
5. Lazy loading модулей
Позволяет загружать модули только при необходимости (по маршруту). Используется в роутинге:
const routes: Routes = \[
{
path: 'admin',
loadChildren: () => import('./admin/admin.module').then(m => m.AdminModule)
}
\];
AdminModule не будет загружен, пока пользователь не перейдёт на /admin.
6. Пример структуры модуля
src/app/
├── features/
│ └── orders/
│ ├── components/
│ ├── services/
│ ├── orders-routing.module.ts
│ ├── orders.module.ts
@NgModule({
declarations: \[OrderListComponent, OrderDetailComponent\],
imports: \[CommonModule, OrdersRoutingModule\],
providers: \[OrdersService\]
})
export class OrdersModule {}
7. forRoot() и forChild() паттерны
Используются для передачи конфигураций или синглтонов:
@NgModule({
providers: \[LoggingService\]
})
export class LoggingModule {
static forRoot(): ModuleWithProviders<LoggingModule> {
return {
ngModule: LoggingModule,
providers: \[LoggingService\]
};
}
}
В AppModule:
imports: \[LoggingModule.forRoot()\]
8. Взаимодействие модулей
Если модуль A экспортирует компонент X, и модуль B хочет использовать X, он должен:
-
Импортировать A
-
X должен быть в A → exports
@NgModule({
declarations: \[X\],
exports: \[X\]
})
export class ModuleA {}
@NgModule({
imports: \[ModuleA\]
})
export class ModuleB {}
9. Рекомендации по организации модулей
-
Используйте feature-модули для каждой бизнес-функции;
-
Создавайте отдельные модули для роутинга (auth-routing.module.ts);
-
Используйте shared/core для повторного использования;
-
Не импортируйте SharedModule в CoreModule;
-
Следите за изоляцией: сервисы в Core, UI-компоненты в Shared;
-
Применяйте lazy loading для разделения бандлов.
10. Standalone компоненты (Angular 14+)
С появлением Standalone компонентов возможно отказаться от NgModule в ряде случаев.
Пример:
@Component({
standalone: true,
selector: 'app-login',
templateUrl: './login.component.html',
imports: \[FormsModule, CommonModule\]
})
export class LoginComponent {}
Можно подключать в роутинг:
{
path: 'login',
component: LoginComponent
}
Несмотря на поддержку Standalone компонентов, NgModule всё ещё актуален в архитектуре крупных приложений.