Пошук уроків, статей та іншого контенту
Підключите ConfigModule і налаштуєте централізоване завантаження параметрів застосунку.
ConfigModuleПараметри застосунку часто залежать від середовища, у якому він запущений:
порт HTTP-сервера;
адреса бази даних;
секретний ключ;
режим роботи застосунку;
назва зовнішнього сервісу.
Зберігати такі значення безпосередньо в коді незручно й небезпечно. Наприклад, секретний ключ не варто додавати до репозиторію.
У NestJS для централізованої роботи з конфігурацією використовується пакет @nestjs/config. Він дає змогу:
завантажувати змінні з файлу .env;
отримувати конфігурацію через ConfigService;
зробити конфігурацію доступною в усьому застосунку.
У корені NestJS-проєкту виконайте:
npm install @nestjs/configПакет @nestjs/config використовує змінні середовища та інтегрується з модульною системою NestJS.
.envСтворіть у корені проєкту файл .env:
PORT=3000
APP_NAME=Book Store
NODE_ENV=developmentФайл .env містить конфігураційні значення у форматі:
ІМ'Я_ЗМІННОЇ=значенняНе додавайте .env до репозиторію, якщо він містить паролі, токени або інші секрети. Зазвичай файл .env додають до .gitignore:
.envДля командної роботи можна створити файл .env.example без реальних секретних значень:
PORT=3000
APP_NAME=Book Store
NODE_ENV=developmentConfigModuleВідкрийте головний модуль застосунку, зазвичай src/app.module.ts, і додайте ConfigModule:
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
}),
],
})
export class AppModule {}Метод forRoot() завантажує конфігурацію під час запуску застосунку.
Опція isGlobal: true робить ConfigModule глобальним. Завдяки цьому не потрібно імпортувати ConfigModule у кожен модуль, де використовується ConfigService.
Без isGlobal: true модуль потрібно імпортувати окремо:
@Module({
imports: [ConfigModule],
})
export class BooksModule {}Для більшості невеликих застосунків зручно підключити конфігурацію глобально.
ConfigServiceПісля підключення модуля можна отримувати значення з .env через ConfigService.
Створимо контролер, який повертає назву застосунку та порт:
import { Controller, Get } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
@Controller('config')
export class ConfigController {
constructor(private readonly configService: ConfigService) {}
@Get()
getConfig() {
const appName = this.configService.get<string>('APP_NAME');
const port = this.configService.get<number>('PORT');
return {
appName,
port,
};
}
}Зареєструємо контролер у модулі:
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { ConfigController } from './config.controller';
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
}),
],
controllers: [ConfigController],
})
export class AppModule {}Тепер після запуску застосунку запит:
GET http://localhost:3000/configповерне приблизно такий результат:
{
"appName": "Book Store",
"port": "3000"
}Значення зі змінних середовища зазвичай надходять як рядки. Тому навіть змінна:
PORT=3000може бути отримана як рядок "3000", а не як число 3000.
Дженерик у цьому прикладі:
this.configService.get<number>('PORT');підказує тип TypeScript, але сам по собі не перетворює рядок на число.
Якщо значення потрібно використовувати саме як число, перетворіть його явно:
const port = Number(this.configService.get<string>('PORT'));Або задайте значення за замовчуванням:
const port = this.configService.get<number>('PORT', 3000);Значення за замовчуванням використовується, якщо змінна PORT не визначена.
Нижче наведено мінімальний приклад застосунку з конфігурацією.
.envPORT=3000
APP_NAME=Book Store
NODE_ENV=developmentsrc/app.module.tsimport { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { ConfigController } from './config.controller';
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
}),
],
controllers: [ConfigController],
})
export class AppModule {}src/config.controller.tsimport { Controller, Get } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
@Controller('config')
export class ConfigController {
constructor(private readonly configService: ConfigService) {}
@Get()
getConfig() {
const appName = this.configService.get<string>('APP_NAME', 'Application');
const environment = this.configService.get<string>(
'NODE_ENV',
'development',
);
const port = Number(this.configService.get<string>('PORT', '3000'));
return {
appName,
environment,
port,
};
}
}src/main.tsimport { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
// Порт також можна отримати з конфігурації в окремому сервісі
await app.listen(3000);
}
bootstrap();Після запуску:
npm run start:devзверніться до:
GET http://localhost:3000/configРезультат буде таким:
{
"appName": "Book Store",
"environment": "development",
"port": 3000
}У цьому прикладі ConfigService використовується для читання параметрів, а ConfigModule.forRoot() завантажує їх із .env.
За замовчуванням ConfigModule шукає файл .env у корені проєкту. Для іншого файлу можна вказати envFilePath:
ConfigModule.forRoot({
isGlobal: true,
envFilePath: '.env.development',
});Також можна передати кілька файлів:
ConfigModule.forRoot({
isGlobal: true,
envFilePath: ['.env.local', '.env'],
});У такому випадку застосунок шукатиме конфігурацію у вказаних файлах.
Якщо змінна може бути відсутньою, задайте значення за замовчуванням:
const appName = this.configService.get<string>(
'APP_NAME',
'Default application',
);Якщо параметр є обов’язковим, краще перевірити його на старті застосунку, а не чекати помилки під час виконання конкретного запиту.
Для початкового використання достатньо перевіряти значення вручну:
const databaseUrl = this.configService.get<string>('DATABASE_URL');
if (!databaseUrl) {
throw new Error('Змінна DATABASE_URL не налаштована');
}ConfigModule не підключеноЯкщо ConfigModule.forRoot() не додано до imports, ConfigService не матиме завантажених значень із .env.
Перевірте app.module.ts:
imports: [
ConfigModule.forRoot({
isGlobal: true,
}),
].envФайл .env має бути в корені проєкту — на одному рівні з package.json.
Правильна структура:
project/
├── .env
├── package.json
├── src/
│ ├── app.module.ts
│ └── main.tsНазва в .env і назва під час отримання значення мають повністю збігатися:
APP_NAME=Book Storethis.configService.get<string>('APP_NAME');APP_NAME, app_name і APP-NAME — це різні назви.
Змінні середовища можуть повертатися як рядки. Якщо потрібне число, виконайте перетворення:
const port = Number(this.configService.get<string>('PORT'));Не додавайте реальні паролі й токени до .env, якщо цей файл відстежується Git. Використовуйте .gitignore, а для прикладу зберігайте лише безпечні шаблонні значення в .env.example.
@nestjs/config призначений для централізованої роботи з конфігурацією.
ConfigModule.forRoot() завантажує змінні середовища, зокрема з .env.
isGlobal: true робить ConfigModule доступним у всьому застосунку.
ConfigService використовується для отримання значень конфігурації.
Значення зі змінних середовища потрібно явно перетворювати на числа або інші типи, якщо це необхідно.
Файли з реальними секретами не слід додавати до репозиторію.