踩坑背景
为什么弃用flutter_dotenv
flutter_dotenv是一个在flutter下可以直接引用键值对格式.env文件的插件。对于写惯了KEY=VALUE格式环境变量的后端码农来说,很方便。
但是flutter_dotenv也有个致命缺点,就是flutter需要将.env文件作为资源打包,才能实现代码对.env的读取。那么如果你的.env中存放了API_BASE_URL或者JWT_SECRET_KEY之类敏感变量的话,ipa文件通过逆向,就有可能获取到你的敏感变量,非常危险!
回归--dart-define,但是新的坑来了
flutter原生加载环境变量的方法就是通过
--dart-define=KEY=VALUE, 或者--dart-define-from-file=.env/dev.json
其中.env文件夹下的dev.json可以是如下格式:
{
"API_BASE_URL": "localhost:8000"
}
但是我发现通过这种方式跑flutter run --dart-define..., 环境变量怎么都不生效。
问题原因
我是通过一个统一的env_config.dart文件,其中所有变量,延用了之前dotenv的写法,用的getter来获取环境变量:
class EnvConfig {
static String get apiBaseUrl => String.fromEnvironment("API_BASE_URL", defaultValue="localhost:8000")
}
这个getter写法就是问题的根源:
- ❌ 使用
getter + String.fromEnvironment():在运行时执行,无法访问编译时定义的值 - ✅ 使用
const 字段 + String.fromEnvironment():在编译时求值,正确获取--dart-define传入的值
核心原则:
String.fromEnvironment()在编译阶段可以获取,打包完成后就被清除,因此在代码运行时以及获取不到了,所以String.fromEnvironment()必须是 const 字段,不能是 getterString.fromEnvironment() / int.fromEnvironment() / bool.fromEnvironment()以此类推
问题解决
修改env_config.dart:
class EnvConfig {
static const String apiBaseUrl = String.fromEnvironment("API_BASE_URL", defaultValue="localhost:8000")
}
问题解决,撒花!