expo的环境变量管理相关问题
原生配置和expo配置间的一些优先级问题
EAS Build打包时出现这个提示:
expo eas build时出现提示:Loaded "env" configuration for the "production" profile: EXPO_PUBLIC_REVENUE_CAT_API_KEY_IOS, EXPO_PUBLIC_REVENUE_CAT_API_KEY_ANDROID, EXPO_PUBLIC_MOONSHOT_BASE_URL. Learn more
Specified value for "android.package" in app.config.js or app.json is ignored because an android directory was detected in the project.
EAS Build will use the value found in the native code.
首先,提示的第一部分是:
Loaded "env" configuration for the "production" profile: EXPO_PUBLIC_REVENUE_CAT_API_KEY_IOS, EXPO_PUBLIC_REVENUE_CAT_API_KEY_ANDROID, EXPO_PUBLIC_MOONSHOT_BASE_URL.
这意味着 Expo 已正确加载了你为 "production" 环境配置的 env
变量。这部分的提示表明你的环境变量(如 EXPO_PUBLIC_REVENUE_CAT_API_KEY_IOS
等)已经被加载,并且将在构建过程中使用。
因此,app.json 中的 env
配置仍然有效,尤其是这些公共的环境变量 (EXPO_PUBLIC_*
)。它们会在构建时被读取并注入到你的应用中。
第二部分的提示是:
Specified value for "android.package" in app.config.js or app.json is ignored because an android directory was detected in the project.
EAS Build will use the value found in the native code.
这句话的意思是,尽管你在 app.json
或 app.config.js
中指定了 android.package
,但由于你的项目中已经存在 android
目录(即你已经弹出到 Expo 管理的原生代码之外),EAS Build 将忽略 app.json
中的 android.package
配置,并优先使用位于原生代码中的包名配置(通常是在 android/app/src/main/AndroidManifest.xml
文件中定义的 package
属性)。
因此,除了 android.package
之外,其他的配置项(如环境变量)仍然可以在 app.json
中继续生效。
app.config.js和eas.json配置环境变量的关联
我用的是公共环境变量 (EXPO_PUBLIC_*
)模式,用process.env.*调用,如改用app.config.js 的extra配置,那么原来eas.json的配置还需要吗?代码调用方式还是process.env吗?
答案如下:
如果你将环境变量配置在 app.config.js
的 extra
字段中,那么 eas.json
中的 env
配置仍然是有用的,但是 你需要改变代码中对环境变量的调用方式。下面是详细的解释。
1. eas.json
配置的作用
eas.json
中的 env
配置决定了 构建时需要注入哪些环境变量。这些环境变量会通过 process.env
注入到你的构建环境中。在你使用 app.config.js
时,eas.json
的 env
配置仍然非常重要,因为它确保了在构建时,环境变量能够被正确地提供给 Expo 项目的配置文件(app.config.js
)。
当你在 eas.json
中配置环境变量时,在构建过程中这些变量会自动加载到 process.env
上。例如:
{
"build": {
"production": {
"env": {
"EXPO_PUBLIC_API_URL": "https://example.com",
"EXPO_PUBLIC_API_KEY": "your-api-key"
}
}
}
}
在 EAS Build 过程中,process.env.EXPO_PUBLIC_API_URL
和 process.env.EXPO_PUBLIC_API_KEY
会被注入。
2. 使用 app.config.js
的 extra
字段
如果你在 app.config.js
中使用 extra
来动态传递环境变量,那么你可以利用 process.env
读取这些变量,并将它们传递到 Expo 的配置中。这样做的好处是,你可 以在 extra
中集中管理所有你需要的环境变量,并通过 expo-constants
访问它们。
例如,app.config.js
文件可以这样写:
export default ({ config }) => {
return {
...config,
extra: {
apiUrl: process.env.EXPO_PUBLIC_API_URL,
apiKey: process.env.EXPO_PUBLIC_API_KEY
}
};
};
这里的 process.env.EXPO_PUBLIC_API_URL
和 process.env.EXPO_PUBLIC_API_KEY
是从 eas.json
中的 env
配置中获取的。
3. 如何在代码中访问这些变量
一旦你在 app.config.js
中配置了 extra
字段,Expo 会将这些 extra
数据注入到应用中,你可以通过 expo-constants
访问它们,而不再需要直接使用 process.env
。
例如:
import Constants from 'expo-constants';
const apiUrl = Constants.expoConfig.extra.apiUrl;
const apiKey = Constants.expoConfig.extra.apiKey;
console.log(apiUrl, apiKey);
通过这种方式,环境变量从 extra
中获取,而不是直接从 process.env
获取。
4. 代码调用方式:从 process.env
转变为 Constants.expoConfig.extra
-
原先的调用:
如果你直接从
process.env
读取环境变量,代码可能是这样的:const apiUrl = process.env.EXPO_PUBLIC_API_URL;
const apiKey = process.env.EXPO_PUBLIC_API_KEY; -
修改后的调用:
当你将环境变量移到
app.config.js
的extra
中后,代码需要改成:import Constants from 'expo-constants';
const apiUrl = Constants.expoConfig.extra.apiUrl;
const apiKey = Constants.expoConfig.extra.apiKey;
5. eas.json
中的配置是否还需要?
是的,eas.json
中的配置依然需要。eas.json
中的 env
配置是 构建时 提供环境变量的地方,供 process.env
在构建时使用。即使你将环境变量放到了 app.config.js
的 extra
中进行管理,eas.json
的 env
配置仍然是注入这些变量的来源。
6. 完整流程
-
在
eas.json
中配置环境变量:这些变量将在构建时注入到process.env
。{
"build": {
"production": {
"env": {
"EXPO_PUBLIC_API_URL": "https://example.com",
"EXPO_PUBLIC_API_KEY": "your-api-key"
}
}
}
} -
在
app.config.js
中使用extra
字段:将process.env
中的环境变量传递到expo
配置中。export default ({ config }) => {
return {
...config,
extra: {
apiUrl: process.env.EXPO_PUBLIC_API_URL,
apiKey: process.env.EXPO_PUBLIC_API_KEY
}
};
}; -
在代码中使用
expo-constants
访问环境变量:import Constants from 'expo-constants';
const apiUrl = Constants.expoConfig.extra.apiUrl;
const apiKey = Constants.expoConfig.extra.apiKey;
console.log(apiUrl, apiKey);
总结
eas.json
中的env
配置仍然需要,因为这是你定义环境变量的地方,它们会在构建时注入。- 代码调用方式需要改变:如果你使用
app.config.js
的extra
字段管理环境变量,代码中应通过Constants.expoConfig.extra
来访问这些变量,而不是直接使用process.env
。
这样做的好处是,你可以在应用中更明确地管理环境变量,并避免直接依赖 process.env
,提供更清晰的结构和更好的可维护性。
我们是不是更推荐app.config.js配置方式?
使用 app.config.js
配置 extra
字段来管理环境变量有多个好处,尤其是在 Expo 或 React Native 项目中。这种方式为项目带来了更多的灵活性、可维护性 和安全性。以下是使用 extra
字段配置环境变量的一些主要好处:
1. 集中管理环境变量
将环境变量集中在 app.config.js
文件的 extra
字段中,可以使项目的配置更加统一和清晰。
-
好处:所有的环境变量都在一个地方定义和管理,无需在不同的文件中查找,避免了环境变量分散在代码各处的混乱。
-
示例:
export default ({ config }) => {
return {
...config,
extra: {
apiUrl: process.env.EXPO_PUBLIC_API_URL,
apiKey: process.env.EXPO_PUBLIC_API_KEY
}
};
};
2. 灵活处理不同环境的配置
app.config.js
是一个 JavaScript 文件,因此你可以根据不同的构建环境(如开发、生产等)动态生成不同的配置。这可以让你更灵活地控制环境变量。
-
好处:可以根据构建环境(如
development
或production
)动态生成不同的extra
配置,避免硬编码。 -
示例:
export default ({ config }) => {
const isProduction = process.env.NODE_ENV === 'production';
return {
...config,
extra: {
apiUrl: isProduction
? process.env.EXPO_PUBLIC_API_URL_PROD
: process.env.EXPO_PUBLIC_API_URL_DEV,
apiKey: process.env.EXPO_PUBLIC_API_KEY
}
};
};在这个例子中,
apiUrl
会根据环境自动选择开发或生产的 URL。
3. 便于访问环境变量
Expo 提供了 expo-constants
模块,可以让你在应用中轻松访问 extra
中的配置。这比直接依赖 process.env
更加直观和安全。
-
好处:通过
Constants.expoConfig.extra
访问环境变量比直接使用process.env
更加安全,有助于避免泄露不必要的信息,并且减少与 Node.js 环境的耦合性。 -
示例:
import Constants from 'expo-constants';
const apiUrl = Constants.expoConfig.extra.apiUrl;
const apiKey = Constants.expoConfig.extra.apiKey;
console.log(apiUrl, apiKey);通过
extra
字段传递的环境变量可以很方便地在应用中获取,并且 Expo 会注入这些变量,简化了访问流程。
4. 避免在客户端暴露敏感信息
Expo 的 extra
字段是专门用于传递客户端需要使用的公共配置。与直接使用 process.env
不同,extra
提供了一种明确的方式来管理哪些变量是需要暴露给客户端的。
- 好处:你可以更清楚地管理哪些变量是安全的、可以暴露给客户端的,而哪些变量不应该暴露。使用
process.env
时,所有变量都可能在客户端暴露,但通过extra
,你可以有选择性地传递需要的变量。
5. 增强安全性和可维护性
通过 app.config.js
的 extra
字段,可以更容易地控制哪些变量是公开的。Expo 中建议将公开的环境变量以 EXPO_PUBLIC_
开头,这样可以明确哪些变量是可以暴露给客户端的,而不需要担心敏感信息被意外泄露。
-
好处:通过
extra
字段,你可以更安全地管理环境变量。你可以确保只有明确标记为EXPO_PUBLIC_
的变量会被加入到extra
中,而不会误将敏感信息暴露给客户端。 -
示例:
export default ({ config }) => {
return {
...config,
extra: {
apiUrl: process.env.EXPO_PUBLIC_API_URL, // 公共 API 地址
apiKey: process.env.EXPO_PUBLIC_API_KEY // 公共 API 密钥
}
};
};
6. 避免在客户端直接使用 process.env
在 React Native 环境中,process.env
并不是像在 Node.js 环境中那样天然存在的。在 Expo 中,直接使用 process.env
可能会导致一些无法预料的问题,尤其 是在不同的构建环境中(比如开发、测试和生产环境)。
- 好处:使用
extra
字段可以避免直接依赖process.env
,这种方式更符合 Expo 和 React Native 的最佳实践,并且可以更好地处理跨平台的环境配置。
7. 简化环境变量的调试
通过 app.config.js
中的 extra
字段,你可以清楚地看到在不同环境下到底哪些变量被注入到了项目中。这比直接依赖 process.env
更加直观。
-
好处:在调试时,你可以通过
console.log
或其他方式查看app.config.js
中的extra
配置,确保环境变量正确注入。 -
示例:
console.log("Extra config:", Constants.expoConfig.extra);
通过这种方式,你可以轻松检查
extra
配置内容,调试环境变量的问题。
8. 与 EAS Build 配合良好
当你使用 EAS Build(Expo Application Services)进行构建时,eas.json
中的环境变量配置会自动注入到 process.env
中。而 app.config.js
的 extra
字段可以利用这些环境变量来生成最终的配置。
-
好处:
extra
字段与 EAS Build 配置(如eas.json
)无缝集成,你可以在eas.json
中配置生产或开发环境的变量,然后通过app.config.js
动态读取这些变量,让构建更加灵活。 -
示例:
在
eas.json
中:{
"build": {
"production": {
"env": {
"EXPO_PUBLIC_API_URL": "https://production.example.com",
"EXPO_PUBLIC_API_KEY": "prod-api-key"
}
},
"development": {
"env": {
"EXPO_PUBLIC_API_URL": "https://dev.example.com",
"EXPO_PUBLIC_API_KEY": "dev-api-key"
}
}
}
}在
app.config.js
中:export default ({ config }) => {
return {
...config,
extra: {
apiUrl: process.env.EXPO_PUBLIC_API_URL,
apiKey: process.env.EXPO_PUBLIC_API_KEY
}
};
};当你在不同环境下构建时(如
production
或development
),EAS Build 会根据eas.json
中的配置自动注入正确的环境变量。
总结
使用 app.config.js
的 extra
字段来管理环境变量的主要好处包括:
- 集中管理:所有环境变量在一个位置统一配置,便于维护。
- 灵活性:可以根据不同环境动态设置不同的
extra
配置。 - 易于访问:通过
Constants.expoConfig.extra
方便地访问环境变量,避免直接使用process.env
。 - 增强安全性:明确哪些变量是安全的、可以暴露给客户端的,避免敏感信息泄露。
- 简化调试:更容易调试和验证环境变量的注入情况。
- 与 EAS Build 集成良好:可以无缝结合 EAS Build 的环境变量配置。
通过这些好处,你可以更好地管理项目中的环境变量,提升项目的可维护性和安全性。
注意,事实证明上述app.config.js的方式只对iOS生效。 而且iOS中也不时出现Constant.expoConfig为undefined的情况,报错:Error: expo-linking needs access to the expo-constants manifest (app.json or app.config.js) to determine what URI scheme to use. Setup the manifest and rebuild 似乎最稳定的方法还是const revenueCatApiKeyIos = process.env.EXPO_PUBLIC_REVENUE_CAT_API_KEY_IOS, 注意如果用解构语法,还是会出错,就是读不出,Android尤为严重。 2024-10-23
附加
destructuring assignment 解构语法获取process.env会得到undefined。 以为是我才遇到,其实网上有讨论。 结论就是:Dont't use destructuring in process.env in most of time.