Модули являются основой структуры приложений на Angular. Каждый Angular-проект организован в виде множества модулей, которые группируют компоненты, директивы, пайпы и сервисы в логические единицы. Модуль является контейнером, обеспечивающим инкапсуляцию и управление зависимостями.
Основным строительным элементом модуля является класс, который
декорируется с помощью декоратора @NgModule. Этот декоратор
принимает объект конфигурации, в котором указываются все компоненты,
сервисы и другие модули, которые должны быть связаны с данным
модулем.
Пример простого модуля:
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { MyComponent } from './my.component';
@NgModule({
declarations: [MyComponent],
imports: [CommonModule],
exports: [MyComponent]
})
export class MyModule {}
Одним из главных принципов разработки на Angular является разделение приложения на независимые модули. Это позволяет достичь высокой модульности и удобства при тестировании, повторном использовании кода и улучшении производительности.
Модуль приложения можно разделить на несколько типов:
Основной модуль (AppModule): это
корневой модуль приложения, который загружается при старте. Он обычно
импортирует все остальные модули.
Ленивые модули (Lazy-loaded Modules): модули, которые загружаются по мере необходимости, что улучшает производительность за счет уменьшения начальной загрузки приложения.
Пример ленивой загрузки модуля:
const routes: Routes = [
{
path: 'feature',
loadChildren: () => import('./feature/feature.module').then(m => m.FeatureModule)
}
];
В данном случае модуль FeatureModule будет загружен
только при переходе на маршрут feature.
Пространства имен в Angular — это механизм для организации и структурирования кода в более крупном приложении. Модули и компоненты часто находятся в различных пространствах имен для предотвращения конфликтов имен и облегчения поиска нужных элементов.
Хотя Angular не требует явного указания пространства имен, можно использовать его в качестве организующего элемента при проектировании сложных приложений. На практике часто используются модули для представления отдельных «пространств» в приложении.
Чтобы избежать конфликтов, Angular предоставляет строгие рекомендации по именованию и организации кода. Например, для модулей, компонентов и сервисов обычно используется подход «папка + имя», что обеспечивает читаемость и предсказуемость:
src/
app/
core/
core.module.ts
logger.service.ts
shared/
shared.module.ts
button.component.ts
feature/
feature.module.ts
feature.component.ts
В этом примере, если бы использовалось пространство имен, можно было
бы указать такие имена, как CoreModule,
LoggerService и так далее. Это обеспечивало бы ясность в
структуре и позволяло бы легче ориентироваться в коде.
Модульная система в Angular способствует декомпозиции больших приложений на более мелкие, логически независимые единицы. Это может быть полезно как для упрощения работы с кодом, так и для улучшения масштабируемости и производительности.
Сначала приложение может быть организовано в несколько крупных модуля, например, один для аутентификации, другой для работы с данными, третий для пользовательского интерфейса. По мере развития приложения эти модули могут быть разбиты на более мелкие и специализированные компоненты, что приведет к лучшей структурированности.
Для сложных приложений может потребоваться создать вложенные модули, каждый из которых будет отвечать за свою часть функционала. Вложенные модули могут использоваться внутри родительских модулей и служить для улучшения организации и инкапсуляции.
Пример:
@NgModule({
declarations: [UserListComponent],
imports: [CommonModule],
exports: [UserListComponent]
})
export class UserModule {}
@NgModule({
imports: [UserModule],
})
export class AppModule {}
В этом примере AppModule импортирует
UserModule, что позволяет использовать все компоненты и
сервисы, экспортируемые из UserModule, внутри
AppModule.
Модульная система в Angular тесно связана с системой инъекций зависимостей (DI). Каждый модуль может предоставлять сервисы для компонентов и других сервисов. Это позволяет централизованно управлять зависимостями и упростить тестирование.
Когда сервис определен в провайдере модуля, его экземпляр будет доступен всем компонентам и сервисам, которые являются частью этого модуля. Если же сервис требуется на уровне всего приложения, его можно предоставить в корневом модуле:
@NgModule({
providers: [AppService]
})
export class AppModule {}
Если сервис требуется только в пределах конкретного модуля, его
следует указать в providers того модуля, где он
используется.
Ленивые модули (lazy loading) дают возможность загружать только те модули, которые действительно необходимы в данный момент. Это уменьшает время загрузки начальной страницы и помогает управлять большими приложениями, разбивая их на более мелкие и независимые части.
В случае использования ленивой загрузки важно правильно структурировать и именовать модули, чтобы не возникало путаницы в их путях и зависимостях. Например:
const routes: Routes = [
{
path: 'products',
loadChildren: () => import('./product/product.module').then(m => m.ProductModule)
}
];
Здесь путь к модулю ProductModule указывается через
динамическую загрузку, что позволяет загружать модуль только при
необходимости.
Модули и пространства имен являются важнейшими элементами в Angular. Они позволяют создавать масштабируемые, легко управляемые и поддерживаемые приложения. Модульная система упрощает инкапсуляцию и внедрение зависимостей, а также помогает разделять приложение на логические части, что улучшает организацию кода и его повторное использование.