Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Що таке глобальні провайдери?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)Глобальний провайдер - провайдер, доступний у всьому застосунку NestJS, навіть якщо модуль, де він оголошений, не імпортовано явно в інші модулі; для цього модуль позначають декоратором `@Global()`, і Nest реєструє його провайдери в кореневому контейнері. **Ключове:** глобальні провайдери варто використовувати лише для інфраструктурних сервісів (логер, конфіг, кеш, автентифікація) - зловживання приховує залежності, ускладнює тестування й може призводити до конфліктів імен; бізнес-логіку краще лишати модульною.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення## Що таке глобальний провайдер **Глобальний провайдер (global provider)** - це провайдер, який **доступний у всьому застосунку NestJS**, навіть якщо модуль, де він оголошений, **не імпортовано явно** в інші модулі. > Іншими словами: якщо ти зареєстрував провайдер як глобальний, > тобі більше не потрібно вказувати `imports: [SomeModule]` у кожному модулі - > NestJS сам робить цей провайдер доступним усюди. ## Приклад без глобального провайдера ```javascript // logger.service.ts @Injectable() export class LoggerService { log(msg: string) { console.log(`[LOG]: ${msg}`); } } // logger.module.ts @Module({ providers: [LoggerService], exports: [LoggerService], }) export class LoggerModule {} ``` Щоб використати `LoggerService` в інших модулях, нам доведеться **імпортувати** `LoggerModule` **вручну** в кожному місці: ```javascript @Module({ imports: [LoggerModule], }) export class UsersModule {} ``` ## Приклад із глобальним провайдером Зробимо модуль **глобальним**, використовуючи декоратор `@Global()`: ```javascript import { Global, Module } from '@nestjs/common'; import { LoggerService } from './logger.service'; @Global() @Module({ providers: [LoggerService], exports: [LoggerService], }) export class LoggerModule {} ``` Тепер `LoggerService` доступний **у всіх модулях** застосунку, навіть якщо `LoggerModule` **ніде не імпортований**. ```javascript @Injectable() export class UsersService { constructor(private readonly logger: LoggerService) {} findAll() { this.logger.log('Fetching users...'); return ['John', 'Alex']; } } ``` NestJS автоматично реєструє `LoggerService` у **глобальному DI-контейнері**, тому він доступний у будь-якому місці без додаткових імпортів. ## Як це працює всередині - Кожен модуль у NestJS має **власну область видимості (scope)**. - Коли ти додаєш `@Global()`, Nest **реєструє провайдери модуля в кореневому контейнері**. - Усі інші модулі "бачать" ці провайдери, навіть не імпортуючи модуль. ## Де це корисно Глобальні провайдери зазвичай використовуються для **кросс-застосунковних сервісів**, наприклад: | Тип сервісу | Приклад | |---|---| | Авторизація | `AuthService`, `JwtService`, `AuthGuard` | | Конфігурація | `ConfigService` з `@nestjs/config` | | Логування | `LoggerService` | | Робота з кешем | `CacheService`, `RedisService` | | Події / сповіщення | `EventBus`, `NotificationService` | ## Важливо: обережно з глобальністю Хоча це зручно, **зловживати глобальними провайдерами не варто**. ### Мінуси: - важко відстежити, звідки приходить залежність; - порушується **інкапсуляція модулів**; - можливі **конфлікти імен** при великій кількості глобальних провайдерів; - тестування ускладнюється (mock потрібно підмінювати глобально). Краще: - використовувати глобальні провайдери **лише для інфраструктури** (логер, конфіг, кеш); - а бізнес-логіку лишати модульною. ## Альтернатива: глобальна реєстрація без `@Global()` Іноді можна зареєструвати **глобальний провайдер програмно**, наприклад, у `main.ts` чи через **Dynamic Module**. ### Приклад через `app.useGlobalFilters()`, `app.useGlobalPipes()`, `app.useGlobalInterceptors()` ```javascript const app = await NestFactory.create(AppModule); app.useGlobalFilters(new HttpExceptionFilter()); app.useGlobalPipes(new ValidationPipe()); app.useGlobalInterceptors(new LoggingInterceptor()); ``` Ці елементи теж стають **глобальними провайдерами**, але на рівні **всього застосунку** (без декоратора `@Global()`). ## Приклад динамічного глобального модуля ```javascript @Global() @Module({}) export class ConfigModule { static forRoot(envFile: string): DynamicModule { return { module: ConfigModule, providers: [ { provide: 'CONFIG_PATH', useValue: envFile, }, ConfigService, ], exports: [ConfigService], }; } } ``` Тепер `ConfigService` глобально доступний усюди. ## Підсумок | Поняття | Опис | |---|---| | Глобальний провайдер | Провайдер, доступний у всіх модулях без явного імпорту | | Створюється через | `@Global()` над модулем, або `useGlobal*()` при ініціалізації | | Використовується для | Загальносистемних сервісів: логер, конфіг, автентифікація | | Переваги | Спрощує архітектуру, менше імпортів | | Недоліки | Приховані залежності, складніше тестувати, ризик конфліктів | | Рекомендація | Роби глобальними лише інфраструктурні сервіси, а бізнес-логіку - модульною |Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.