Expo 中的环境变量
编辑
了解如何在 Expo 项目中使用环境变量。
环境变量是在源代码之外配置的键值对,允许你的应用根据环境的不同而表现不同。例如,在构建应用的测试版本时,可以启用或禁用某些功能,或在为生产环境构建时切换到不同的 API 端点。
Expo CLI 将自动从 .env 文件中加载带有 EXPOPUBLIC 前缀的环境变量,以在您的 JavaScript 代码中使用,当您使用 Expo CLI 时,例如在本地开发模式下通过 npx expo start 启动应用程序。
读取 .env 文件中的环境变量
在项目根目录创建一个 .env 文件,并在新行以 EXPO_PUBLIC_[NAME]=VALUE 的形式添加环境特定变量:
EXPO_PUBLIC_API_URL=https://staging.example.com EXPO_PUBLIC_API_KEY=abc123
现在你可以在源代码中直接使用环境变量:
import { Button } from 'react-native'; function Post() { const apiUrl = process.env.EXPO_PUBLIC_API_URL; async function onPress() { await fetch(apiUrl, { ... }) } return <Button onPress={onPress} title="Post" />; }
当你运行 npx expo start 时,在你的应用程序包中 process.env.EXPO_PUBLIC_API_URL 将被替换为 https://staging.example.com。变量可以在编辑代码时更新,而无需重新启动 Expo CLI 或清除缓存。你需要执行完整重新加载(例如,摇动手势,然后在 Expo Go 或开发构建中点击 Reload)以查看更新后的值。
不要在EXPO_PUBLIC_变量中存储敏感信息,例如私钥。这些变量将在编译后的应用程序中以明文形式显示。
变量加载方式
Expo CLI 根据 标准 .env 文件解析 加载 .env 文件,然后将代码中对 process.env.EXPO_PUBLIC_[VARNAME] 的所有引用替换为在 .env 文件中设置的相应值。出于安全原因,位于 node_modules 里的代码不会被影响。
如何读取环境变量
-
每个环境变量必须作为属性的静态引用使用 JavaScript 的点记法来对
process.env进行内联。 例如,表达式process.env.EXPO_PUBLIC_KEY是有效的并且会被内联。 -
不支持该表达式的其他版本。例如,
process.env['EXPO_PUBLIC_KEY']或const {EXPO_PUBLIC_X} = process.env无效且将不会 可以内联。
使用多个 .env 文件定义不同环境
你可以定义任何 标准的 .env 文件,因此可以拥有单独的 .env 和 .env.local 文件,并且它们将按照标准优先级加载。
你可以选择提交默认的 .env 文件或其他标准配置,但通常 .env.local 文件应添加到你的 .gitignore,因为它们用于指定与你的本地机器相关的环境配置(例如,当你需要向本地服务器发出请求时,可能需要的网络 IP 地址等)。
.env*.local
环境变量与 NODE_ENV
我们建议不要使用 NODE_ENV 在不同的 .env 文件之间切换(例如 .env.test 和 .env.production)。虽然在技术上可以实现(NODE_ENV=test npx expo start 将加载 .env.test)——但这可能不会按你预期的方式工作。例如,npx expo export 总是强制 NODE_ENV 为 production,因此 NODE_ENV=test npx expo export 实际上不会在 NODE_ENV 设置为 test 的情况下运行该命令。
在 Expo CLI 命令之上构建的其他工具也会表现出相同的行为——例如,eas update 调用 npx expo export,因此 NODE_ENV=test eas update 同样不会在 NODE_ENV 设置为 test 的情况下运行(它会是 production)。NODE_ENV 环境变量被许多工具以不同的方式使用(例如,如果你运行 NODE_ENV=production npm install,你的 devDependencies 将不会被安装),我们发现对于 React Native 项目,最好不要为此用例再额外重载它。
如果你使用 EAS,考虑改用 eas env:pull。这会把你的 .env.local 与你选择的环境进行替换,而不是依赖 NODE_ENV。你也可以在不使用 EAS 的情况下,通过编写脚本覆盖 .env.local 或 .env,以获得与你希望工作的环境相匹配的内容,从而实现类似的行为。
禁用环境变量
Expo CLI 的环境变量有两个部分,且两者都可以被禁用:
- Expo CLI 会自动将 .env 文件加载到全局进程中。要禁用此行为,请在运行任意 Expo CLI 命令之前将环境变量
EXPO_NO_DOTENV设置为1:EXPO_NO_DOTENV=1。 - Expo 的 Metro 配置在客户端 JavaScript 包中包含环境变量的内联序列化。要禁用此行为,可以使用
EXPO_NO_CLIENT_ENV_VARS=1。
如果你在环境变量方面遇到问题,你可以尝试禁用其中一个或这两个功能中的一个或两个。
Expo 应用服务中的环境变量
EAS Build
EAS Build 使用 Metro Bundler 来构建嵌入在应用程序二进制中的 JavaScript bundle,因此它会使用与您的构建作业一起上传的 .env 文件,将 EXPOPUBLIC 变量内联到您的代码中。EAS Build 还允许在 eas.json 的构建配置文件和通过 EAS Secrets 定义环境变量。有关更多信息,请查看 EAS Build 文档中的环境变量与构建机密。
EAS Update
EAS Update 在本地环境或 CI 中使用 Metro Bundler 来构建应用包,因此它将使用可用的 .env 文件将 EXPO_PUBLIC_ 变量内联到代码中。有关更多信息,请查看 EAS Update 文档中的 环境变量。
迁移到 Expo 环境变量
来自 react-native-config
将你的 .env 文件更新为在 JavaScript 代码中使用的变量前缀为 EXPO_PUBLIC_:
- API_URL=https://myapi.com + EXPO_PUBLIC_API_URL=https://myapi.com
如果你有任何非标准的 .env 文件(例如 .env.staging),你将需要将它们迁移到其中一个 标准的 .env 文件。
然后更新你的代码以使用 process.env.EXPO_PUBLIC_[VARNAME]:
- import Config from 'react-native-config'; - const apiUrl = Config.API_URL; + const apiUrl = process.env.EXPO_PUBLIC_API_URL;
来自 babel-plugin-transform-inline-environment-variables
使用 Babel 插件将代码中的环境变量引用进行转换,类似于 Expo 的环境变量工作方式。将变量放入一个 .env 文件中,并将变量名更新为以 EXPO_PUBLIC_ 前缀:
- const apiUrl = process.env.API_URL; + const apiUrl = process.env.EXPO_PUBLIC_API_URL;
然后你可以从你的 Babel 配置 中移除该插件:
module.exports = function (api) { api.cache(true); return { presets: ['babel-preset-expo'], -- plugins: ['transform-inline-environment-variables'], }; };
在更新你的 Babel 配置文件后,请务必使用 npx expo start --clear 清除缓存。
来自 direnv
将 JavaScript 中使用的任何环境变量从它们的 .envrc 文件移动到一个 .env 文件,并在前缀前加上 EXPO_PUBLIC_。
以前使用 direnv 时,你需要使用一个 dynamic app config 来读取 process.env 以在 extra 字段中设置环境变量,这样它们就可以通过 expo-constants 在你的 JavaScript 代码中使用。请将这些引用直接移动到你的代码中,并添加 EXPO_PUBLIC_ 前缀:
- import Constants from 'expo-constants'; - const apiUrl = Constants.expoConfig.extra.apiUrl; + const apiUrl = process.env.EXPO_PUBLIC_API_URL;
direnv自动根据你当前的目录在你的 shell 中加载和卸载环境变量,这意味着它会影响同一目录下运行的任何进程的环境变量,不仅仅是 Expo CLI。你很可能希望继续为在你的 JavaScript 代码中不使用的其他环境变量继续使用direnv。
安全注意事项
切勿将前缀为 EXPO_PUBLIC_ 的环境变量中的敏感秘密存储起来。当最终用户运行你的应用时,他们可以访问应用中的所有代码和嵌入的环境变量。有关存储敏感信息的更多信息,请阅读 存放敏感信息。