如何向React Native主文件传递环境变量
React Native 获取环境变量的可行方案
我帮你整理几个实际项目里验证过的靠谱方案,解决你遇到的环境变量传递问题:
方案一:使用 react-native-dotenv 库(最常用)
这是社区最流行的环境变量管理工具,能直接把.env文件里的变量注入到JS代码中,还支持多环境区分,完美适配你提到的Xcode运行场景。
安装依赖
npm install react-native-dotenv --save-dev # 或者用yarn yarn add react-native-dotenv --dev配置Babel
在项目根目录的babel.config.js里添加插件:module.exports = { presets: ['module:metro-react-native-babel-preset'], plugins: [ ['module:react-native-dotenv', { moduleName: '@env', path: '.env', allowUndefined: true }] ] };创建环境变量文件
在根目录创建.env、.env.development、.env.production等文件,比如:# .env.development APP_ENV=development API_URL=https://dev-api.example.com在JS代码中使用
import { APP_ENV, API_URL } from '@env'; console.log(`当前环境:${APP_ENV}`); console.log(`接口地址:${API_URL}`);Xcode适配
如果用Xcode运行,需要指定加载的环境文件:- 打开Xcode,选择你的scheme → Edit Scheme → Run → Arguments
- 在Environment Variables里添加
NODE_ENV,值设为development或production - 这样metro会自动加载对应的
.env.${NODE_ENV}文件
方案二:修改Metro配置手动注入环境变量
如果不想依赖第三方库,可以直接修改Metro的打包配置,把系统环境变量注入到JS全局中。
修改
metro.config.js
在项目根目录的metro.config.js里添加如下配置:const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config'); const config = {}; module.exports = mergeConfig(getDefaultConfig(__dirname), { transformer: { getTransformOptions: async () => ({ transform: { experimentalImportSupport: false, inlineRequires: true, }, }), }, resolver: { extraNodeModules: { process: require.resolve('process/browser'), }, }, }); // 把环境变量挂载到全局 global.__ENV__ = { APP_ENV: process.env.APP_ENV || 'development', API_URL: process.env.API_URL || 'https://dev-api.example.com', };在JS代码中使用
直接访问全局变量即可:console.log(`当前环境:${global.__ENV__.APP_ENV}`);启动时传递环境变量
命令行启动时这样传参:APP_ENV=development API_URL=https://dev-api.example.com npx react-native run-ios对于Xcode,同样在scheme的Environment Variables里添加这些变量,Metro会自动读取。
方案三:原生端配置+Native Modules暴露
如果需要原生端和JS端共享环境变量,可以在iOS/Android的原生配置里设置,再通过Native Modules暴露给JS。
iOS端
- 打开Xcode,选择项目 → Build Settings → 添加User-Defined Settings,比如
APP_ENV和API_URL - 编辑
Info.plist,添加对应的键值对,值引用刚才的设置:<key>APP_ENV</key> <string>$(APP_ENV)</string> <key>API_URL</key> <string>$(API_URL)</string> - 写一个简单的Native Module读取Info.plist内容:
// RNEnvironmentManager.m #import <React/RCTBridgeModule.h> @interface RNEnvironmentManager : NSObject <RCTBridgeModule> @end @implementation RNEnvironmentManager RCT_EXPORT_MODULE(); RCT_EXPORT_METHOD(getEnvironment:(RCTResponseSenderBlock)callback) { NSDictionary *infoDict = [[NSBundle mainBundle] infoDictionary]; NSString *appEnv = infoDict[@"APP_ENV"]; NSString *apiUrl = infoDict[@"API_URL"]; callback(@[@{@"APP_ENV": appEnv, @"API_URL": apiUrl}]); } @end - JS端调用:
import { NativeModules } from 'react-native'; const { RNEnvironmentManager } = NativeModules; RNEnvironmentManager.getEnvironment((env) => { console.log(`当前环境:${env.APP_ENV}`); });
Android端
- 在
android/app/build.gradle里添加:android { defaultConfig { buildConfigField "String", "APP_ENV", "\"${System.getenv("APP_ENV") ?: "development"}\"" buildConfigField "String", "API_URL", "\"${System.getenv("API_URL") ?: "https://dev-api.example.com"}\"" } } - 写Native Module暴露BuildConfig内容:
// EnvironmentModule.java package com.yourapp; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.Promise; public class EnvironmentModule extends ReactContextBaseJavaModule { public EnvironmentModule(ReactApplicationContext reactContext) { super(reactContext); } @Override public String getName() { return "EnvironmentModule"; } @ReactMethod public void getEnvironment(Promise promise) { String appEnv = BuildConfig.APP_ENV; String apiUrl = BuildConfig.API_URL; WritableMap map = Arguments.createMap(); map.putString("APP_ENV", appEnv); map.putString("API_URL", apiUrl); promise.resolve(map); } } - JS端调用方式和iOS一致。
额外小贴士
- 记得把
.env文件加入.gitignore,避免敏感信息提交到仓库 - 可以在
package.json里写脚本简化多环境切换:"scripts": { "start:dev": "APP_ENV=development npx react-native start", "run:ios:dev": "APP_ENV=development npx react-native run-ios", "run:ios:prod": "APP_ENV=production npx react-native run-ios" }
内容的提问来源于stack exchange,提问作者YardenST




