在Flutter应用开发过程中,如果应用支持多种环境配置(如开发、预发布、生产环境),并且需要与Firebase进行集成,那么就需要额外进行一些配置工作,确保每种环境配置都对应不同的Firebase环境。
最佳实践是为每种环境配置创建独立的Firebase项目,这样能够将开发、预发布和生产环境相互隔离。

在使用自定义后端或像Supabase这样的Dart SDK时,我们可以通过切换URL和API密钥,使应用在不同环境配置下连接到正确的后端环境。然而,Firebase的集成情况有所不同,它没有提供直接的Dart SDK,并且还需要进行一些特定于平台的设置,这使得多环境配置过程变得更加复杂。
幸运的是,FlutterFire CLI可以帮助我们解决这些难题。接下来,我将逐步引导你了解如何使用它为Flutter和Firebase应用配置多环境,让整个过程变得轻松简单。
本文将涵盖以下内容:
- 为什么需要使用FlutterFire?
- Firebase和FlutterFire CLI的安装方法
- 多环境配置下FlutterFire的配置语法
- 利用Shell脚本简化配置流程
- 在应用启动时初始化Firebase(适用于iOS、Android和Web平台)
读完本文后,你将能够熟练地将Firebase集成到多环境的Flutter应用中,节省开发时间 ,同时避免常见的配置问题。
前提条件
请注意:本文假设你已经拥有一个Flutter应用,并且该应用能够通过
dev
(开发)、stg
(预发布)和prod
(生产)这几种环境配置,在iOS和Android平台上正常运行,具体运行命令如下:
bash
flutter run --flavor dev
flutter run --flavor stg
flutter run --flavor prod
此外,你还需要准备三个对应的Firebase项目,例如:

如果大家对Flutter多环境有兴趣,可以在评论区留言,我可以再做一期多环境相关的。
一切准备就绪?那我们开始吧!🚀
为什么需要FlutterFire?
过去,Firebase的集成本身就是一个相当繁琐的过程,你需要为每个平台下载配置文件,比如iOS平台的GoogleService-Info.plist
文件和Android平台的google-services.json
文件。
而现在,这个过程变得简单多了。你只需要运行flutterfire configure
命令,然后按照一些交互式提示进行操作即可。完成操作后,这些文件会自动添加到项目中,包括:
lib/firebase_options.dart
ios/Runner/GoogleService-Info.plist
android/app/google-services.json
不过,在处理多环境配置时,情况就变得复杂起来。你需要为每种环境配置准备不同版本的这些文件,并且将它们存储在不同位置,以防止在配置过程中出现文件覆盖的问题。
幸运的是,FlutterFire 1.0.0版本增加了对多环境配置的支持。下面我们就来详细了解一下如何使用这项功能。
安装Firebase和FlutterFire CLI
官方文档中详细介绍了安装Firebase和FlutterFire CLI的所有步骤。
Firebase CLI可以作为一个独立的库安装,也可以通过npm安装。对于会使用npm
的开发者来说,npm
安装的方式更友好且可靠:
bash
npm install -g firebase-tools
我最终选择安装的二进制,因为我的node并不兼容riebase CLI,而我又不太想折腾版本,毕竟我不会nodejs:
bash
curl -sL https://firebase.tools | bash
安装完成后,可通过运行firebase --version
命令检查安装是否成功。
接下来,运行firebase login
命令进行登录,执行命令后会出现如下提示:
bash
? Allow Firebase to collect CLI and Emulator Suite usage and error reporting information? Yes
此时会自动打开一个浏览器窗口,你需要使用与目标Firebase项目关联的Google账号进行登录。选择账号登录后,会出现相关授权提示。
点击"Allow"并关闭浏览器窗口,至此Firebase CLI就完成了登录操作。
注意:务必使用与目标Firebase项目关联的Google账号登录。如果使用了错误的账号,可以先运行
firebase logout
命令退出登录,然后再次运行firebase login
重新登录。
安装FlutterFire CLI
安装FlutterFire CLI的命令如下:
bash
dart pub global activate flutterfire_cli
安装完成后,运行flutterfire --version
命令,检查是否安装了1.0.0或更高版本。
多环境配置下FlutterFire的配置语法
以生成dev
环境配置文件的命令为例:
bash
flutterfire config \
--project=flutter-ship-dev \
--out=lib/firebase_options_dev.dart \
--ios-bundle-id=com.jarvanmo.dev \
--ios-out=ios/flavors/dev/GoogleService-Info.plist \
--android-package-name=com.jarvanmo.dev \
--android-out=android/app/src/dev/google-services.json
各参数说明如下:
--project
:指定要使用的Firebase项目(注意:需传入项目ID,而非别名)。--out
:Firebase配置文件的输出路径。--ios-bundle-id
:iOS应用的Bundle ID((打开Xcode,然后通过以下顺序找到Bundle ID:Runner>General>Identity>Bundle Identifier))。--ios-out
:iOS平台GoogleService-Info.plist
文件的输出路径。--android-package-name
:Android应用的包名(在android/app/build.gradle.kts
中,找到applicationId
对应的值)。--android-out
:Android平台google-services.json
文件的输出路径。
要了解所有可用的选项,可以运行
flutterfire config --help
。
使用该命令时,可按以下步骤操作:
- 将命令复制到终端中。
- 根据应用实际情况,更新
project
、ios-bundle-id
和android-package-name
参数。 - 运行命令,并按照交互式提示进行操作(后续会详细介绍这些提示)。
但是,你需要对stg
和prod
环境配置重复上述操作,这样既耗时又容易出错。
下面我们来看看如何实现这个过程的自动化。👇
利用Shell脚本简化配置流程
虽然flutterfire config
命令已经帮我们完成了大部分工作,但仍需要为每种环境配置分别运行该命令,并设置不同的参数。
为了简化操作,我们可以在项目根目录下创建一个flutterfire-config.sh
脚本,内容如下:
bash
#!/bin/bash
# 用于为不同环境/flavor生成Firebase配置文件的脚本
# 欢迎复用和修改此脚本以适配你的项目
if [[ $# -eq 0 ]]; then
echo "错误:未指定环境。请使用'dev'、'stg'或'prod'。"
exit 1
fi
case $1 in
dev)
flutterfire config \
--project=flutter-ship-dev \
--out=lib/firebase_options_dev.dart \
--ios-bundle-id=com.codewithandrea.flutterShipApp.dev \
--ios-out=ios/flavors/dev/GoogleService-Info.plist \
--android-package-name=com.codewithandrea.flutter_ship_app.dev \
--android-out=android/app/src/dev/google-services.json
;;
stg)
flutterfire config \
--project=flutter-ship-stg \
--out=lib/firebase_options_stg.dart \
--ios-bundle-id=com.codewithandrea.flutterShipApp.stg \
--ios-out=ios/flavors/stg/GoogleService-Info.plist \
--android-package-name=com.codewithandrea.flutter_ship_app.stg \
--android-out=android/app/src/stg/google-services.json
;;
prod)
flutterfire config \
--project=flutter-ship-prod \
--out=lib/firebase_options_prod.dart \
--ios-bundle-id=com.codewithandrea.flutterShipApp \
--ios-out=ios/flavors/prod/GoogleService-Info.plist \
--android-package-name=com.codewithandrea.flutter_ship_app \
--android-out=android/app/src/prod/google-services.json
;;
*)
echo "错误:指定的环境无效。请使用'dev'、'stg'或'prod'。"
exit 1
;;
esac
有了这个脚本,虽然仍需要为项目设置正确的参数,但只需要设置一次。
之后,生成所有Firebase配置文件就变得非常轻松,无需背下每个参数了。
现在,是时候运行这个脚本了。👇
为每种环境配置运行FlutterFire脚本
若要配置dev
环境,运行以下命令:
bash
./flutterfire-config.sh dev
运行命令后,会出现提示,首先选择要配置的平台:
bash
? Which platforms should your configuration support (use arrow keys & space to select)? ›
✔ android
✔ ios
macos
✔ web
windows
接下来,选择iOS上的Build configuration
:
bash
? You have to choose a configuration type. Either build configuration (most likely choice) or a target set up. ›
❯ Build configuration
Target
接着,选择Debug-dev
构建配置:
bash
? Please choose one of the following build configurations ›
Debug
Release
Profile
❯ Debug-dev
Profile-dev
Release-dev
Debug-stg
Profile-stg
Release-stg
Debug-prod
Profile-prod
Release-prod
当然你可以通过重复运行该脚本实现更细致的Build configuration
配置
注意:如果遇到"Failed to list Firebase projects"错误,可先运行
firebase logout
命令,然后再运行firebase login
命令,之后重新尝试。
这一步可能会花费一些时间,因为CLI需要在Firebase中注册必要的应用。如果配置成功,会看到类似以下的确认信息:
bash
✔ You have to choose a configuration type. Either build configuration (most likely choice) or a target set up. · Build configuration
✔ Please choose one of the following build configurations · Debug-dev
i Found 40 Firebase projects. Selecting project flutter-ship-dev.
✔ Which platforms should your configuration support (use arrow keys & space to select)? · android, ios, web
i Firebase android app com.codewithandrea.flutter_ship_app.dev is not registered on Firebase project flutter-ship-dev.
i Registered a new Firebase android app on Firebase project flutter-ship-dev.
i Firebase ios app com.codewithandrea.flutterShipApp.dev is not registered on Firebase project flutter-ship-dev.
i Registered a new Firebase ios app on Firebase project flutter-ship-dev.
i Firebase web app flutter_ship_app (web) is not registered on Firebase project flutter-ship-dev.
i Registered a new Firebase web app on Firebase project flutter-ship-dev.
Firebase configuration file lib/firebase_options_dev.dart generated successfully with the following Firebase apps:
Platform Firebase App Id
web 1:424176442589:web:c86e231d1eeaba0e90cf34
android 1:424176442589:android:c5841ba53606b4c490cf34
ios 1:424176442589:ios:592b56a800affa4e90cf34
Learn more about using this file and next steps from the documentation:
> https://firebase.google.com/docs/flutter/setup
接下来,通过运行以下命令为stg
环境配置重复相同的操作:
bash
./flutterfire-config.sh stg
最后,为prod
环境配置运行:
bash
./flutterfire-config.sh prod
完成上述操作后,项目中会生成以下新文件:
lib/firebase_options_dev.dart
lib/firebase_options_stg.dart
lib/firebase_options_prod.dart
ios/flavors/dev/GoogleService-Info.plist
ios/flavors/stg/GoogleService-Info.plist
ios/flavors/prod/GoogleService-Info.plist
android/app/src/dev/google-services.json
android/app/src/stg/google-services.json
android/app/src/prod/google-services.json
Firebase配置文件是否应提交到Git?
上述生成的配置文件本身并不包含敏感信息,因此从安全角度来说,将它们提交到Git仓库是可行的。
FlutterFire配置完成✅
如果按照上述所有步骤操作且未出现错误,此时所有的Firebase配置文件应该都已正确生成并添加到项目中。
在使用Firebase运行应用之前,还需要完成以下几个步骤:
- 安装
firebase_core
包,并验证应用在Android和iOS平台上能否正常运行。 - 在应用启动时初始化Firebase。
下面我们逐步来看。👇
安装firebase_core
包
在终端中运行以下命令,添加firebase_core
包:
bash
flutter pub add firebase_core
flutter pub get
在Android平台运行应用
如果你的Android应用是使用FlutterFire CLI 1.1.0或更高版本进行配置的,理论上应该可以正常运行,不会出现错误。
但如果FlutterFire设置不正确,可能会遇到以下错误:
bash
Plugin [id: 'com.google.gms.google-services'] was not found in any of the following sources:
- Gradle Core Plugins (plugin is not in 'org.gradle' namespace)
- Included Builds (No included builds contain this plugin)
- Plugin Repositories (plugin dependency must include a version number for this source)
要解决这个问题,打开android/settings.gradle.kts
文件,确保已将com.google.gms.google-services
作为插件添加,内容如下:
kotlin
plugins {
id("dev.flutter.flutter-plugin-loader") version "1.0.0"
id("com.android.application") version "8.7.0" apply false
// START: FlutterFire Configuration
id("com.google.gms.google-services") version("4.3.15") apply false
// END: FlutterFire Configuration
id("org.jetbrains.kotlin.android") version "1.8.22" apply false
}
同样,在android/app/build.gradle.kts
文件的plugins
块中,也应包含该插件:
kotlin
plugins {
id("com.android.application")
// START: FlutterFire Configuration
id("com.google.gms.google-services")
// END: FlutterFire Configuration
id("kotlin-android")
// Flutter Gradle插件必须在Android和Kotlin Gradle插件之后应用
id("dev.flutter.flutter-gradle-plugin")
}
应用此修复后,Android应用应该就能正常运行了。
注意:你可以在Google的Maven仓库中找到
com.google.gms.google-services
的最新版本。
在iOS平台运行应用
在运行iOS应用之前,打开ios/Podfile
文件,确保平台版本设置为13.0
或更高,内容如下:
ruby
# Uncomment this line to define a global platform for your project
platform :ios, '13.0'
运行pod install
命令后,应该就可以在iOS平台上正常运行应用了。
在应用启动时初始化Firebase
根据官方文档,应将Firebase初始化代码添加到lib/main.dart
文件中,示例如下:
dart
import 'package:flutter_ship_app/firebase_options.dart';
// 在main()函数中
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
然而,这种默认设置并不适用于我们的多环境配置场景,因为我们为每种环境配置都创建了单独的配置文件:
那么,该如何解决这个问题呢?
方案1:集中式Firebase初始化逻辑
一种解决方法是创建一个firebase.dart
文件,内容如下:
dart
// firebase.dart
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:flutter_ship_app/firebase_options_prod.dart' as prod;
import 'package:flutter_ship_app/firebase_options_stg.dart' as stg;
import 'package:flutter_ship_app/firebase_options_dev.dart' as dev;
Future<void> initializeFirebaseApp() async {
// 根据构flavor确定使用哪个Firebase选项
final firebaseOptions = switch (appFlavor) {
'prod' => prod.DefaultFirebaseOptions.currentPlatform,
'stg' => stg.DefaultFirebaseOptions.currentPlatform,
'dev' => dev.DefaultFirebaseOptions.currentPlatform,
_ => throw UnsupportedError('无效的构建风味: $flavor'),
};
await Firebase.initializeApp(options: firebaseOptions
};
}
通过这种方式,它会根据`appFlavor`常量的值进行判断,返回对应环境配置的`FirebaseOptions`对象。
需要注意的是,在Flutter web上使用`--flavor`选项运行时,会收到环境配置不完全支持的警告,但`appFlavor`常量依然能返回正确的值。
此时,在`lib/main.dart`中只需简单调用`await initializeFirebaseApp()`即可完成初始化,`lib/main.dart`依旧作为应用的单一入口点:
```dart
import 'firebase.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await initializeFirebaseApp();
runApp(const MainApp());
}
采用这种设置,Flutter应用就能根据不同的环境配置,初始化并连接到对应的Firebase项目。
然而,这种方案存在一个隐患。👇
所有Firebase配置文件都会被打包(无法进行Tree Shaking)
仔细查看firebase.dart
文件可以发现,虽然会根据flavor选择正确的Firebase配置,但三个firebase_options_*.dart
文件都被导入了:
dart
// firebase.dart
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
// 注意:三个文件均被导入
import 'package:flutter_ship_app/firebase_options_prod.dart' as prod;
import 'package:flutter_ship_app/firebase_options_stg.dart' as stg;
import 'package:flutter_ship_app/firebase_options_dev.dart' as dev;
Future<void> initializeFirebaseApp() async {
// 根据flavor确定使用哪个Firebase选项
final firebaseOptions = switch (appFlavor) {
'prod' => prod.DefaultFirebaseOptions.currentPlatform,
'stg' => stg.DefaultFirebaseOptions.currentPlatform,
'dev' => dev.DefaultFirebaseOptions.currentPlatform,
_ => throw UnsupportedError('无效的构建风味: $flavor'),
};
await Firebase.initializeApp(options: firebaseOptions);
}
这意味着在构建过程中,由于switch
操作是在运行时进行的,无法通过Tree shaking
去除未使用的代码,三个配置文件都会被编译并打包进最终的应用。
从理论上讲,如果有人对应用进行逆向工程,就有可能获取到开发或预发布环境的详细信息,而这些环境的安全性通常不如生产环境。
对于不涉及敏感数据的应用,这或许不是大问题,但它始终是一个潜在风险。如果想完全规避该风险,可以考虑采用更安全的方案。👇
方案2:使用多个入口点
如前所述,以下代码存在一定问题:
dart
import 'package:flutter_ship_app/firebase_options_prod.dart' as prod;
import 'package:flutter_ship_app/firebase_options_stg.dart' as stg;
import 'package:flutter_ship_app/firebase_options_dev.dart' as dev;
更安全的做法是创建三个独立的入口点文件------main_dev.dart
、main_stg.dart
和main_prod.dart
,示例如下:
dart
// main_dev.dart
import 'package:flutter_ship_app/firebase_options_dev.dart';
import 'main.dart';
void main() async {
runMainApp(DefaultFirebaseOptions.currentPlatform);
}
这些文件仅负责导入对应的firebase_options_*.dart
文件,并将配置参数传递给main.dart
中的函数,由该函数执行实际的初始化操作。main.dart
文件内容示例如下:
dart
// main.dart
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
void runMainApp(FirebaseOptions firebaseOptions) async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(options: firebaseOptions);
runApp(const MainApp());
}
这种方式确保每个构建版本仅包含所需的Firebase配置文件,是管理多环境配置的安全高效方案。
那么,如何使用正确的环境配置运行应用呢?👇
使用特定环境配置运行应用
若采用上述第二种方案,项目中会有四个相关文件:
main_dev.dart
:dev
环境配置的入口点main_stg.dart
:stg
环境配置的入口点main_prod.dart
:prod
环境配置的入口点main.dart
:包含应用初始化核心代码
可以通过以下命令以特定环境配置运行应用:
bash
flutter run --flavor dev -t lib/main_dev.dart
flutter run --flavor stg -t lib/main_stg.dart
flutter run --flavor prod -t lib/main_prod.dart
如此一来,每种环境配置都能使用对应的入口点,确保应用启动时连接到正确的Firebase环境。
若采用此方案,记得更新本地配置文件(如.vscode/launch.json
)和CI/CD脚本,以适配这些改动。
该选择哪种方案?
两种方案各有利弊,具体选择需结合项目需求:
- 方案1:集中式Firebase初始化 。该方案实现起来更简单快捷,允许使用单一的
main.dart
文件,通过运行时的动态逻辑处理不同环境配置下的Firebase选项。但由于所有Firebase配置文件都会被打包进最终应用,从安全角度考虑,并非最佳选择。 - 方案2:为每种环境配置设置多个入口点。此方案前期配置工作较多,需要为每种环境配置创建独立的入口点文件。不过,它仅会为每个构建版本打包必要的Firebase配置文件,能有效防止攻击者获取其他环境的详细信息,安全性更高。
尽管方案2前期配置相对繁琐,但对于使用Firebase的多环境Flutter应用,我更推荐采用该方案。👍
方案1更适用于非Firebase应用场景,此时可以使用--dart-define-from-file
,并在.env.dev
、.env.stg
、.env.prod
等单独文件中为每种环境配置定义环境变量。想了解更多内容,可阅读我之前写过的《flutter工程化之动态配置》。
总结
通过将FlutterFire与简单的Shell脚本相结合,原本复杂易错的多环境配置流程得到了极大简化。现在,无需再为每种环境配置手动配置Firebase,仅需使用一个脚本就能为所有环境生成所需文件,既节省时间,又降低了出错概率。
集中式Firebase初始化方案提供了一种快速便捷的方法,借助单一的main.dart
文件和运行时逻辑,使应用在启动时连接到正确的Firebase项目。然而,该方案会将所有Firebase配置文件打包,对于安全性要求较高的应用不太适用。
多入口点方案则确保每个构建版本仅包含必要的Firebase配置,在处理敏感数据或开发生产级应用时,是更优的选择。
无论采用哪种方案,Flutter应用都能自动连接到对应的Firebase环境(dev
、stg
或prod
),确保应用在开发和生产的各个阶段都能稳定运行。

这种配置方式让Flutter与Firebase应用的多环境管理变得轻松许多,我自己在生产应用中也一直在使用,效果非常好。✅