Архитектура NestJS: модули, провайдеры, DI
↑ 6.2 NestJS · → Следующая
Зачем это на собесе
Если в вакансии есть Node.js/NestJS, спросят про модули и DI; знание ASP.NET Core помогает объяснить по аналогии.
Объяснение
NestJS — фреймворк для серверных приложений на TypeScript поверх Express или Fastify. Архитектура вдохновлена Angular и ASP.NET.
| Понятие | Роль |
|---|---|
Module (@Module) | группирует контроллеры и провайдеры, задаёт границы; imports, providers, controllers, exports |
Provider (@Injectable) | сервис, репозиторий, фабрика — то, что внедряется |
Controller (@Controller) | обрабатывает HTTP-запросы |
| Dependency Injection | внедрение через конструктор по токену (обычно класс) |
| Scope | DEFAULT (singleton), REQUEST, TRANSIENT |
@Injectable()
export class OrdersService {
constructor(private readonly repo: OrdersRepository, private readonly config: ConfigService) {}
find(id: string) { return this.repo.findById(id); }
}
@Module({
imports: [ConfigModule],
controllers: [OrdersController],
providers: [OrdersService, OrdersRepository],
exports: [OrdersService], // доступен другим модулям
})
export class OrdersModule {}Кастомные провайдеры: useClass, useValue, useFactory (асинхронная фабрика), useExisting; токены-строки/символы с @Inject('TOKEN'). Динамические модули (forRoot, forRootAsync) настраиваются при импорте.
Нюансы и подводные камни
- Провайдер, не экспортированный из модуля, недоступен снаружи.
- Циклические зависимости лечатся
forwardRef, но чаще указывают на плохую декомпозицию. REQUEST-scope распространяется вверх по цепочке зависимостей и замедляет приложение.- Декораторы работают через
reflect-metadataи требуютemitDecoratorMetadata. - Не создавайте экземпляры вручную (
new Service()): теряется DI.
Практика
- Создайте модуль заказов с сервисом и репозиторием.
- Подключите провайдер через
useFactoryс асинхронной инициализацией. - Напишите динамический модуль с
forRoot.
Вопросы с ответами
Как устроен DI в NestJS?
Провайдеры регистрируются в модулях, контейнер разрешает зависимости по типам/токенам конструктора и управляет временем жизни.
Зачем exports?
Чтобы сделать провайдер модуля доступным импортирующим модулям.