flutter-config
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseFlavor Architecture
Flavor架构
- Define three flavors: ,
dev,stagingprod - Use a single entry point for all flavors
main.dart - Pass flavor-specific configuration via :
--dart-define-from-filebashflutter 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.dartentry pointsmain_prod.dart
- 定义三种flavor:、
dev、stagingprod - 所有flavor统一使用**单个**作为入口文件
main.dart - 通过传入flavor专属配置:
--dart-define-from-filebashflutter 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 directory at project root:
config/config/ ├── dev.json ├── staging.json └── prod.json - Example :
config/dev.jsonjson{ "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 to
config/*.jsonif they contain any environment-specific secrets; otherwise commit them for team convenience.gitignore
- 将各flavor的JSON配置文件存放在项目根目录的文件夹下:
config/config/ ├── dev.json ├── staging.json └── prod.json - 示例:
config/dev.jsonjson{ "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 or
String.fromEnvironment('KEY')bool.fromEnvironment('KEY') - Use a sealed enum:
Flavorsealed class Flavor { dev, staging, prod } - is a singleton holding flavor, base URL, feature flags, and Firebase config
AppConfig
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') - 使用密封枚举:
Flavorsealed class Flavor { dev, staging, prod } - 是单例类,存储flavor、基础URL、功能开关和Firebase配置
AppConfig
Environment Configuration
环境配置
- Store per-flavor config in a centralized class:
AppConfig- — API endpoint per environment
baseUrl - — verbose logging for dev only
enableLogging - — disabled in dev
enableCrashlytics - — display name per flavor (e.g., "MyApp Dev", "MyApp")
appName
- All values come from the JSON file via — NO hardcoded per-flavor logic in Dart code
--dart-define-from-file - NEVER put secrets in the JSON config files — use or CI-injected env vars
flutter_secure_storage
- 将各flavor的配置存放在统一的类中:
AppConfig- ——各环境对应的API端点
baseUrl - ——仅开发环境开启详细日志
enableLogging - ——开发环境关闭
enableCrashlytics - ——各flavor对应的应用显示名(例如「MyApp Dev」、「MyApp」)
appName
- 所有取值都通过从JSON文件获取——Dart代码中不要硬编码任何flavor专属逻辑
--dart-define-from-file - 切勿将密钥存放在JSON配置文件中——请使用或CI注入的环境变量
flutter_secure_storage
Platform-Specific Flavor Setup
平台专属Flavor配置
Android
Android
- Define and
flavorDimensionsinproductFlavors:android/app/build.gradlegroovyflavorDimensions "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:productFlavorsgroovyflavorDimensions "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、显示名和签名信息
- 在中将Flutter flavor与Xcode scheme做映射
ios/Runner.xcodeproj
Firebase Per-Flavor
各Flavor的Firebase配置
- Use separate Firebase projects per flavor (dev, staging, prod)
- Place (Android) and
google-services.json(iOS) in flavor-specific directoriesGoogleService-Info.plist - Use with
flutterfire configureflag for each environment--project
- 每个flavor使用独立的Firebase项目(dev、staging、prod)
- 将(Android)和
google-services.json(iOS)存放在flavor专属目录下GoogleService-Info.plist - 为每个环境执行时添加
flutterfire configure参数指定对应项目--project
Build Commands
构建命令
bash
undefinedbash
undefinedDevelopment
开发环境
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
undefinedflutter 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
undefinedRules
规范
- 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 and
--flavorexplicitly--dart-define-from-file - Use a single — NEVER create separate entry points per flavor
main.dart
- 切勿硬编码环境专属取值(URL、API密钥、功能开关)
- 切勿将生产环境密钥提交到代码仓库
- 所有团队成员必须能够通过单条命令在本地运行任意flavor
- CI/CD流水线必须显式指定和
--flavor两个参数--dart-define-from-file - 使用单个——切勿为每个flavor创建独立的入口文件
main.dart