Рішення для гнучких та організованих конфігурацій у Node.js

💡 Усі статті, обговорення, новини про Front-end — в одному місці. Приєднуйтесь до Front-end спільноти!

Файли .env традиційно використовуються для управління конфігураціями у Node.js, проте вони мають деякі недоліки:

  • Відсутність структури змінних.
  • Ризик конфліктів імен.
  • «Шум» у глобальному середовищі (process.env).

Щоб вирішити ці проблеми, багато років тому я створив модуль config-in-files. Спершу це було локальне рішення для моїх проєктів, а зараз, в рамках цієї статті, я публікую його як npm-пакет. Можливо він приверне вашу увагу

Усвідомлюю, що існують інші підходи, можливо, сучасніші й досконаліші. Я вже багато років не займають активно аутсорсом і мої знання про популярні бібліотеки могли застаріти. Цей модуль може стати в пригоді розробникам, які шукають простий і ефективний спосіб організації конфігурацій, але остаточну думку я залишаю на розгляд спільноти.

У цій статті я розповім про основні можливості config-in-files, покажу, які проблеми він вирішує, і наведу приклади коду.

Проблеми, які вирішує config-in-files

1. Погана видимість у process.env

Традиційно .env-файли додають змінні до глобального об’єкта process.env. Це призводить до таких проблем:

  • Відсутність структури: Усі змінні зберігаються на одному рівні, що ускладнює їх організацію та пошук.
  • Конфлікти імен: У деяких проєктах важко слідкувати за назвами змінних.
  • Шум у даних: process.env містить як конфігураційні, так і системні змінні.

Рішення:

  • Кожна група конфігурацій розбивається на окремі файли.
  • config-in-files автоматично збирає дані у структурований об’єкт, де ім’я файлу стає ключем об’єкта.

Приклад:

Файл конфігурації ’project_dir/config/server.js’:

const config = { port: 8080 };
export default config;

Використання

import config from 'config-in-files'; 
const { port } = await config.server; // 8080

2. Складність роботи із зовнішніми файлами

Деякі типи конфігурацій (наприклад, криптографічні ключі або сертифікати) незручно зберігати у .env. Часто їх вказують лише як шляхи до файлів, що призводить до таких труднощів:

  • Жорстка залежність від файлової структури: Будь-яка зміна структури папок оточення потребує редагування шляхів у .env.
  • Додаткова логіка в коді: Завантаження та обробка файлів ускладнює основний код програми.

Рішення:

  • Модуль виступає посередником між джерелом параметра та його використанням.
  • Підтримується логіка завантаження або генерації значень, незалежно від джерела.
  • Всі параметри зводяться в єдину структуру, полегшуючи доступ до них.

Приклад:

Файл конфігурації `project_dir/config/auth.js`

import path from 'node:path';
import fs from 'node:fs/promises';

// Отримуємо абсолютний шлях до файлу
const envKey = process.env.PRIV_KEY;
const projectDir = process.cwd();
const keyPath = path.join(projectDir, envKey);

// прочитати ключ у файлі
const key = await fs.readFile(keyPath, 'utf-8');
// Створюємо конфігураційний об'єкт
const config = { keys: { priv: key } };
// Експортуємо конфігурацію
export default config; 

Використання

import config from 'config-in-files';

const { priv } = await config.auth.keys; // приватний ключ

3. Оточення Dev, Prod та інші

config-in-files не має вбудованих інструментів для роботи з різними оточеннями, що є певним недоліком. Зізнаюся, я згадав про це вже в процесі написання статті. У найближчий час я можу додати таку функціональність, якщо цей модуль знайде підтримку. Особисто я зараз працюю в іншій сфері, тому ця можливість вже не є для мене критичною. Це може бути реалізовано у вигляді додаткових файлів, наприклад: server.js, server.dev.js, server.prod.js та інші. У цьому підході server.js буде працювати за замовчуванням, а файли на кшталт server.dev.js перевизначатимуть співпадаючі ключі з server.js за умови, що NODE_ENV=dev.

Наразі можна використовувати змінну середовища NODE_ENV для керування конфігураціями для розробки, продакшену або інших оточень таким чином:

Приклад:

// Визначаємо середовище на основі NODE_ENV
const env = process.env.NODE_ENV;

// Вибір порту залежно від середовища
const port = env === 'dev' ? 5000 : 8080;

// Створюємо конфігураційний об'єкт
const config = { port };
// Експортуємо конфігурацію
export default config;

Використання

import config from 'config-in-files';

// Отримуємо значення порту з конфігурації
const { port } = await config.server; 
console.log(port);

// Якщо NODE_ENV не вказано, використовуватиметься значення за замовчуванням
// { port: 8080 }

// Якщо NODE_ENV=dev, то значення буде
// { port: 5000 }

У підсумку

config-in-files задумувався як легкий і простий інструмент для роботи з конфігураціями у проєктах на Node.js. Це дуже базовий модуль.

Хоча я вже багато років не займаюсь активною розробкою аутсорс-проєктів і не можу з упевненістю сказати, наскільки це рішення актуальне сьогодні, цей модуль не раз допомагав мені впорядкувати конфігурації в проєктах раніше, особливо коли джерелами параметрів була не тільки консоль.

Я публікую його, щоб отримати вашу оцінку ідеї та, за потреби, ви можете використати її у своїх власних проєктах. Ваші відгуки допоможуть удосконалити цей інструмент або дізнатися про його релевантність у сучасних реаліях.

👍ПодобаєтьсяСподобалось0
До обраногоВ обраному0
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

Підписатись на коментарі