Добавить объявление

Настройка окружений во Flutter приложении с помощью Flavors

Когда приложение выходит за пределы пет-проекта, возникает необходимость держать окружения раздельно. Dev, Staging и Production должны жить своей жизнью: с разными API-ключами, бэкендом, а иногда даже иконками и названиями. В Flutter эта задача решается через Flavors. Рассказываю, как настроить и не запутаться.

Что такое Flavors и зачем они нужны:


Flavors (или схемы в iOS, продуктные варианты в Android) позволяют из одной кодовой базы собирать разные варианты приложения. У каждого варианта могут быть свои:

  • URL бэкенда и ключи API.

  • Имя приложения и bundle ID.

  • Иконки и сплеш-скрины.

  • Настройки сборки и зависимости.


Это дает возможность установить на устройство одновременно dev-версию и продовую, не боясь, что они перезатрут друг друга. И главное - исключает случайную отправку тестового кода в релиз.

Организация кода:


Самый простой способ - сделать отдельные точки входа для каждого окружения. В папке lib создаем файлы:

  • main_dev.dart

  • main_staging.dart

  • main_prod.dart


В каждом передаем в приложение идентификатор среды, чтобы внутри можно было подставлять нужные конфиги.

void main() {
runApp(MyApp(environment: 'DEV'));
}

Android - настройка productFlavors:


В android/app/build.gradle добавляем секцию:

flavorDimensions "default"
productFlavors {
dev {
dimension "default"
applicationIdSuffix ".dev"
versionNameSuffix "-dev"
}
staging {
dimension "default"
applicationIdSuffix ".staging"
versionNameSuffix "-staging"
}
production {
dimension "default"
}
}

Это даст разные имена пакетов: .dev, .staging и основное. Приложения не будут конфликтовать при установке.

iOS - схемы и бандлы:


В Xcode нужно продублировать схему Runner для каждого окружения и задать разные идентификаторы бандла в настройках таргета. Например:

  • com.example.app.dev

  • com.example.app.staging

  • com.example.app


В Info.plist можно выставить разные названия приложений, чтобы в меню было видно, какая версия запущена.

Запуск и сборка:


Для запуска нужного flavor используем флаги:

flutter run --flavor dev -t lib/main_dev.dart
flutter build apk --flavor prod -t lib/main_prod.dart
flutter build ios --flavor staging -t lib/main_staging.dart

Управление конфигурацией:


Внутри кода удобно сделать класс с константами для каждого окружения:

class AppConfig {
static const Map apiUrls = {
'DEV': 'https://dev.api.example.com',
'STAGING': 'https://staging.api.example.com',
'PROD': 'https://api.example.com',
};
}

А в приложении просто обращаться по ключу, который пришел из main-файла.

Иконки для каждого flavor:


Пакет flutter_launcher_icons умеет генерировать иконки под разные flavors. В pubspec.yaml прописываем:

flutter_launcher_icons:
flavors:
dev:
image_path: "assets/icons/dev_icon.png"
staging:
image_path: "assets/icons/staging_icon.png"
production:
image_path: "assets/icons/prod_icon.png"

Запускаем и получаем разные иконки для каждого окружения.

Лучшие практики:


  • Не храните ключи и секреты прямо в коде. Используйте .env файлы или безопасное хранилище.

  • Ведите имена flavors одинаково на Android и iOS - меньше путаницы.

  • Настройте CI/CD так, чтобы пайплайны собирали каждый flavor отдельно.

  • Для тестировщиков dev-сборка должна визуально отличаться (иконка, цвет темы), чтобы случайно не перепутали с продакшеном.


Вывод:


Flavors - это не про «сделать красиво», а про контроль и безопасность. Правильная настройка окружений убережет от случайных деплоев с тестовыми данными и позволит команде спокойно работать, не боясь что-то сломать в бою. Один раз настроив, вы сэкономите часы нервотрепки и багов на пустом месте.
04.03.2026 19 301