flutter-config

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Flavor Architecture

Flavor架构

  • Define three flavors:
    dev
    ,
    staging
    ,
    prod
  • Use a single
    main.dart
    entry point for all flavors
  • Pass flavor-specific configuration via
    --dart-define-from-file
    :
    bash
    flutter run --flavor dev --dart-define-from-file=config/dev.json
    flutter run --flavor staging --dart-define-from-file=config/staging.json
    flutter run --flavor prod --dart-define-from-file=config/prod.json
  • NEVER create separate
    main_dev.dart
    ,
    main_staging.dart
    ,
    main_prod.dart
    entry points
  • 定义三种flavor:
    dev
    staging
    prod
  • 所有flavor统一使用**单个
    main.dart
    **作为入口文件
  • 通过
    --dart-define-from-file
    传入flavor专属配置:
    bash
    flutter run --flavor dev --dart-define-from-file=config/dev.json
    flutter run --flavor staging --dart-define-from-file=config/staging.json
    flutter run --flavor prod --dart-define-from-file=config/prod.json
  • 切勿创建独立的
    main_dev.dart
    main_staging.dart
    main_prod.dart
    入口文件

Config JSON Structure

配置JSON结构

  • Store per-flavor JSON config files in a
    config/
    directory at project root:
    config/
    ├── dev.json
    ├── staging.json
    └── prod.json
  • Example
    config/dev.json
    :
    json
    {
      "FLAVOR": "dev",
      "BASE_URL": "https://api-dev.example.com",
      "APP_NAME": "MyApp Dev",
      "ENABLE_LOGGING": "true",
      "ENABLE_CRASHLYTICS": "false"
    }
  • NEVER put secrets (API keys, signing credentials) in these JSON files — use CI-injected env vars or
    flutter_secure_storage
  • Add
    config/*.json
    to
    .gitignore
    if they contain any environment-specific secrets; otherwise commit them for team convenience
  • 将各flavor的JSON配置文件存放在项目根目录的
    config/
    文件夹下:
    config/
    ├── dev.json
    ├── staging.json
    └── prod.json
  • config/dev.json
    示例:
    json
    {
      "FLAVOR": "dev",
      "BASE_URL": "https://api-dev.example.com",
      "APP_NAME": "MyApp Dev",
      "ENABLE_LOGGING": "true",
      "ENABLE_CRASHLYTICS": "false"
    }
  • 切勿将密钥(API密钥、签名凭证)存放在这些JSON文件中——请使用CI注入的环境变量或
    flutter_secure_storage
    存储
  • 如果
    config/*.json
    包含任何环境专属密钥,请将其添加到
    .gitignore
    中;否则可提交到代码仓库方便团队使用

Entry Point Pattern

入口文件模式

dart
// lib/main.dart
void main() {
  const flavor = String.fromEnvironment('FLAVOR', defaultValue: 'dev');
  AppConfig.init(flavor: Flavor.fromString(flavor));
  runApp(const App());
}
  • Read all compile-time values via
    String.fromEnvironment('KEY')
    or
    bool.fromEnvironment('KEY')
  • Use a sealed
    Flavor
    enum:
    sealed class Flavor { dev, staging, prod }
  • AppConfig
    is a singleton holding flavor, base URL, feature flags, and Firebase config
dart
// lib/main.dart
void main() {
  const flavor = String.fromEnvironment('FLAVOR', defaultValue: 'dev');
  AppConfig.init(flavor: Flavor.fromString(flavor));
  runApp(const App());
}
  • 通过
    String.fromEnvironment('KEY')
    bool.fromEnvironment('KEY')
    读取所有编译期变量
  • 使用密封
    Flavor
    枚举:
    sealed class Flavor { dev, staging, prod }
  • AppConfig
    是单例类,存储flavor、基础URL、功能开关和Firebase配置

Environment Configuration

环境配置

  • Store per-flavor config in a centralized
    AppConfig
    class:
    • baseUrl
      — API endpoint per environment
    • enableLogging
      — verbose logging for dev only
    • enableCrashlytics
      — disabled in dev
    • appName
      — display name per flavor (e.g., "MyApp Dev", "MyApp")
  • All values come from the JSON file via
    --dart-define-from-file
    — NO hardcoded per-flavor logic in Dart code
  • NEVER put secrets in the JSON config files — use
    flutter_secure_storage
    or CI-injected env vars
  • 将各flavor的配置存放在统一的
    AppConfig
    类中:
    • baseUrl
      ——各环境对应的API端点
    • enableLogging
      ——仅开发环境开启详细日志
    • enableCrashlytics
      ——开发环境关闭
    • appName
      ——各flavor对应的应用显示名(例如「MyApp Dev」、「MyApp」)
  • 所有取值都通过
    --dart-define-from-file
    从JSON文件获取——Dart代码中不要硬编码任何flavor专属逻辑
  • 切勿将密钥存放在JSON配置文件中——请使用
    flutter_secure_storage
    或CI注入的环境变量

Platform-Specific Flavor Setup

平台专属Flavor配置

Android

Android

  • Define
    flavorDimensions
    and
    productFlavors
    in
    android/app/build.gradle
    :
    groovy
    flavorDimensions "environment"
    productFlavors {
        dev { dimension "environment"; applicationIdSuffix ".dev"; resValue "string", "app_name", "MyApp Dev" }
        staging { dimension "environment"; applicationIdSuffix ".staging"; resValue "string", "app_name", "MyApp Staging" }
        prod { dimension "environment"; resValue "string", "app_name", "MyApp" }
    }
  • android/app/build.gradle
    中定义
    flavorDimensions
    productFlavors
    groovy
    flavorDimensions "environment"
    productFlavors {
        dev { dimension "environment"; applicationIdSuffix ".dev"; resValue "string", "app_name", "MyApp Dev" }
        staging { dimension "environment"; applicationIdSuffix ".staging"; resValue "string", "app_name", "MyApp Staging" }
        prod { dimension "environment"; resValue "string", "app_name", "MyApp" }
    }

iOS

iOS

  • Create Xcode schemes for each flavor (Dev, Staging, Prod)
  • Use xcconfig files for per-flavor bundle ID, display name, and signing
  • Map Flutter flavors to Xcode schemes in
    ios/Runner.xcodeproj
  • 为每个flavor创建对应的Xcode scheme(Dev、Staging、Prod)
  • 使用xcconfig文件配置各flavor的包ID、显示名和签名信息
  • ios/Runner.xcodeproj
    中将Flutter flavor与Xcode scheme做映射

Firebase Per-Flavor

各Flavor的Firebase配置

  • Use separate Firebase projects per flavor (dev, staging, prod)
  • Place
    google-services.json
    (Android) and
    GoogleService-Info.plist
    (iOS) in flavor-specific directories
  • Use
    flutterfire configure
    with
    --project
    flag for each environment
  • 每个flavor使用独立的Firebase项目(dev、staging、prod)
  • google-services.json
    (Android)和
    GoogleService-Info.plist
    (iOS)存放在flavor专属目录下
  • 为每个环境执行
    flutterfire configure
    时添加
    --project
    参数指定对应项目

Build Commands

构建命令

bash
undefined
bash
undefined

Development

开发环境

flutter run --flavor dev --dart-define-from-file=config/dev.json
flutter run --flavor dev --dart-define-from-file=config/dev.json

Staging

预发布环境

flutter run --flavor staging --dart-define-from-file=config/staging.json
flutter run --flavor staging --dart-define-from-file=config/staging.json

Production release

生产环境打包

flutter build appbundle --flavor prod --dart-define-from-file=config/prod.json --release flutter build ipa --flavor prod --dart-define-from-file=config/prod.json --release
undefined
flutter build appbundle --flavor prod --dart-define-from-file=config/prod.json --release flutter build ipa --flavor prod --dart-define-from-file=config/prod.json --release
undefined

Rules

规范

  • NEVER hardcode environment-specific values (URLs, API keys, feature flags)
  • NEVER commit production secrets to the repository
  • Every team member MUST be able to run any flavor locally with a single command
  • CI/CD pipelines MUST specify both
    --flavor
    and
    --dart-define-from-file
    explicitly
  • Use a single
    main.dart
    — NEVER create separate entry points per flavor
  • 切勿硬编码环境专属取值(URL、API密钥、功能开关)
  • 切勿将生产环境密钥提交到代码仓库
  • 所有团队成员必须能够通过单条命令在本地运行任意flavor
  • CI/CD流水线必须显式指定
    --flavor
    --dart-define-from-file
    两个参数
  • 使用单个
    main.dart
    ——切勿为每个flavor创建独立的入口文件