Для разработки приложений стандартно создаются 2-3 основных окружения. В разных командах названия у них могут немного отличаться, но суть всегда одна:
🔴production — пользовательское окружение, берет реальные данные с бэкенда, в таком виде приложение попадет в сторы
🔴staging — окружение для тестирования взаимодействия с бэкендом, дает тестовые серверные данные и позволяет имитировать разные пользовательские сценарии
🔴development — окружение для внутренних процессов разработки, может управлять внутренними моковыми данными для тестирования логики работы приложения
В проектах с несколькими окружениями часто нужно подменять те или иные переменные динамически между prod, stage и dev. Именно для этого есть переменные оружения, которые стандартно хранятся в .env файлах.
Представим, что нам нужно настроить передачу переменых во все три окружения в нашем проекте. Для этого создадим в корне проекта директорию env со следующей структурой.
❗️Файлы .env необходимо добавлять в .gitignore и никогда не загружать в репозитории.
env
|_ prod.env
|_ stage.env
|_ dev.env
В каждый из файлов необходимо добавить те данные, которые в проекте должны подменяться от окружения к окружению. У нас это будет baseUrl для запросов на сервер и ключ API для доступа к AppMetrica.
requestBaseUrl='https://base-url.ru/'
appMetricaApiKey='your_api_key'
Чтобы приложение могло использовать эти переменные, подключим библиотеку envied. Она не только даст доступ к данным переменных, но и поможет зашифровать их, хранить в формате неочевидных наборов целых чисел.
Такая безопасность — главное преимущество этого пакета: данные переменных не будут использоваться в приложении в явном виде. Это значит, что при реверс-инжиниринге и прочих механизмах извлечения данных программного кода получить к ним доступ будет значительно сложнее.
Чтобы приложение получило доступ к переменным создадим интерфейс конфигурации
abstract interface class AppConfigInterface {
abstract final String requestBaseUrl;
abstract final String appMetricaApiKey;
}
Для каждого из окружений добавим реализацию интерфейса конфигурации с аннотацией класса
@Envied(). Аннотация требует пути к файлу, откуда будут извлечены переменные окружения. Поля внутри класса помечаются аннотацией
@EnviedField() — сюда можно передать параметры названия переменной, значения по умолчанию, необходимости офусцировать данные и другие данные.
@Envied(name: 'Prod', path: 'env/prod.env')
class AppConfigProd implements AppConfigInterface {
@override
@EnviedField(obfuscate: true)
String get appMetricaApiKey => _AppConfigProd.appMetricaApiKey;
@override
@EnviedField(obfuscate: true)
String get requestBaseUrl => _AppConfigProd.requestBaseUrl;
}
После запуска кодогенерации объекты с аннотацией получают свои значения из указанного по пути файла .env. Зашифрованные значения в приложении хранятся в файле app_config.g.dart.
Готово! Теперь вы можете внедрить объект конфигурации в DI приложения и безопасно использовать переменные окружения!
