Совсем недавно начал изучать фреймворк Fastify, который почему-то не особо популярен в русскоязычном сегменте интернета. Для хранения переменных конфигурации я всегда использовал файл .env. Для чтения файла .env на Express я привык использовать всем известную библиотеку dotenv, то врем как в экосистеме Fastify есть своя библиотека - @fastify-env.

Я в обратился к документации... и ничего не понял. Я попробовал реализовать то, что там указано, но у меня ничего не вышло. Туториал на youtube от какого-то индуса так же не помог (хотя у индийского программиста всё получилось)...

Сославшись на позднее время суток и усталость мозга, я сдался и начал искать какое-нибудь готовое решение в интернете, и оно нашлось достаточно быстро. Выяснилось, что я не один сталкиваюсь с такой проблемой и это частая сложность у программистов пришедших в Fastify после Express.

Итак, ниже пойдёт перевод этой статьи от 27.07.2021 г. (обновлено 18.02.2022 г.). Перед прочтением статьи рекомендую потратить 5-10 минут времени на чтение ооочень короткой официальной документации библиотеки @fastify-env.


Проблема: как мне получить доступ к моему файлу .env в Fastify?

Исходя из опыта работы в Express, я привык использовать модуль dotenv для чтения переменных конфигурации, таких как имя пользователя и пароль для базы данных, secret для jsonwebtokens и другие, из моего файла .env.

Подключившись к экосистеме плагинов fastify, я установил fastify-env и попытался использовать его для загрузки содержимого моего файла .env. Первоначальная проблема, с которой я столкнулся, заключалась в том, что документация для доступа к переменным .env с использованием fastify-env казалась немного скудной, и я не смог найти ни одного хорошего руководства.

Попробовав несколько разных подходов с помощью fastify-env и не сумев прочитать переменные из .env, я сдался и установил dotenv. Этот подход сработал, и я смог успешно подключить fastify к базе данных MongoDB. Однако огромным недостатком использования dotenv с fastify является то, что переменные .env недоступны в экземпляре fastify, поэтому доступ к ним из модулей, скрытых в структуре каталогов, быстро становится головной болью.

 Я планировал использовать jsonwebtokens в своем приложении для аутентификации пользователей на серверной части. Чтобы их проверить, мне нужно сохранить 'секрет' на сервере и получить к нему доступ из разных модулей, которые включают логику проверки. Хотя решение dotenv работало достаточно хорошо для учетных данных базы данных, оно было слишком громоздким для доступа к 'секрету'. Итак, я  снова попробовал fastify-env.

Решение или ключевые моменты, которые я пропустил

Используя fastify в первый раз, я столкнулся сразу с несколькими новыми  концепциями и пропустил несколько важных элементов в своих первых попытках использовать fastify-env. Надеюсь, следующее краткое изложение моего опыта поможет другим новичкам в fastify-env сэкономить время и усилия.

Переменные файла .env должны быть включены в схему (shema)

Первое, что я пропустил при первой попытке использования fastify-env, это то, что переменные в файле .env должны быть включены в схему, используемую fastify-env, иначе они будут недоступны. Следующие фрагменты кода дают пример того, как это работает:

.env

USERNAME=databaseUsername
PASSWORD=doubleSecretDatabasePassword

server.js

const schema = {
  type: 'object',
  required: ['PASSWORD', 'USERNAME'],
  properties: {
    PASSWORD: {
      type: 'string'
    },
    USERNAME: {
      type: 'string'
    }
  }
}

Установите для ключа "data" значение "process.env"

Второй ключевой момент, который я пропустил, заключался в том, что для ключа данных в объекте options необходимо установить значение "process.env" для чтения файла .env. Недостаточно просто установить для ключа dotenv значение true. Следующий фрагмент кода показывает, как правильно установить оба ключа.

server.js

const options = {
  dotenv: true,
  data: process.env
}

Функция ready() работает не так как я думал в начале.

Третья и последняя вещь, которую я не понял при первоначальной попытке использовать fastify-env, заключалась в том, что ожидание fastify.ready() перед fastify.listen() не загружает все плагины по порядку. Однако ожидание fastify.after() в строке после fastify.register() гарантирует, что переменные .env будут определены после fastify.after() , как показано в следующем фрагменте кода.

server.js

fastify.register(fastifyEnv, options)
await fastify.after()

// Теперь переменные .env определены

Соберём всё это вместе!

Следующий фрагмент кода показывает все мое решение с использованием fastify-env для настройки URL-адреса подключения для аутентификации в базе данных MongoDB с использованием значений имени пользователя и пароля, заданных в файле .env.

server.js

// Fastify
const fastify = require('fastify')({
  logger: true
})

const fastifyEnv = require('fastify-env')
const schema = {
  type: 'object',
  required: ['DB_PASSWORD', 'DB_USERNAME'],
  properties: {
    DB_PASSWORD: {
      type: 'string'
    },
    DB_USERNAME: {
      type: 'string'
    }
  }
}

const options = {
  confKey: 'config',
  schema,
  dotenv: true,
  data: process.env
}

const initialize = async () => {
  fastify.register(fastifyEnv, options)
  await fastify.after()

  // Database
  // Connection URL
  const username = encodeURIComponent(fastify.config.DB_USERNAME)
  const password = encodeURIComponent(fastify.config.DB_PASSWORD)
  const dbName = 'databaseName'

  const url = `mongodb://${username}:${password}@localhost:27017/${dbName}`

  fastify.register(require('./database-connector'), {
    url,
    useUnifiedTopology: true
  })
}

initialize()

// Запуск сервера
(async () => {
  try {
    await fastify.ready()
    await fastify.listen(process.env.PORT)
  } catch (error) {
    fastify.log.error(error)
    process.exit(1)
  }
})()

Я надеюсь, что другие программисты найдут это полезным. Кроме того, если у кого-либо из экспертов fastify-env есть предложения по улучшению этого подхода, пожалуйста, не стесняйтесь оставлять их в комментариях. Спасибо за чтение и удачного кодирования!

Пожалуйста, обратите внимание: "database-connection" - это плагин fastify, который я написал для использования официального драйвера MongoDB версии 4.x, потому что в то время fastify-mongodb использовал драйвер 3.x под капотом. С тех пор fastify-mongodb был обновлен для использования драйвера 4.x, поэтому, вероятно, используйте его в своем проекте.


На этом всё! Я так же как и автор статьи надеюсь, что начинающим программистам (коим и я являюсь) эта статья сэкономит время и нервы, ибо я сам изрядно намучился пытаясь самостоятельно всё это дело настроить.

P.S. это моя первая статья на Хабре, буду рад комментариям и обратной связи по содержанию статьи.

Комментарии (0)