在react-native中设置环境variables?

我正在使用react-native构build一个跨平台的应用程序,但我不知道如何设置环境variables,以便我可以为不同的环境使用不同的常量。

例:

development: BASE_URL: '', API_KEY: '', staging: BASE_URL: '', API_KEY: '', production: BASE_URL: '', API_KEY: '', 

而不是硬编码你的应用程序常量和切换环境(我会解释如何做到这一点),我build议使用十二个因素的build议让你的构build过程定义你的BASE_URL和你的API_KEY

为了回答如何将您的环境暴露给react-native ,我build议使用Babel的babel-plugin-transform-inline-environment-variables 。

为了得到这个工作,你需要下载插件,然后你需要设置一个.babelrc ,它应该看起来像这样:

 { "presets": ["react-native"], "plugins": [ "transform-inline-environment-variables" ] } 

所以如果你通过运行API_KEY=my-app-id react-native bundle (或者start,run-ios,或者run-android)来传输你的react-native代码,那么你所要做的就是让你的代码如下所示:

 const apiKey = process.env['API_KEY']; 

然后巴别将用下面的代替:

 const apiKey = 'my-app-id'; 

希望这可以帮助!

React native没有全局variables的概念。 它严格执行模块化范围 ,以提高组件的模块化和可重用性。

但有时候,您需要组件来了解其环境。 在这种情况下,定义一个Environment组件可以调用以获取环境variables非常简单,例如:

environment.js

 var _Environments = { production: {BASE_URL: '', API_KEY: ''}, staging: {BASE_URL: '', API_KEY: ''}, development: {BASE_URL: '', API_KEY: ''}, } function getEnvironment() { // Insert logic here to get the current platform (eg staging, production, etc) var platform = getPlatform() // ...now return the correct environment return _Environments[platform] } var Environment = getEnvironment() module.exports = Environment 

我-component.js

 var Environment = require('./environment.js') ...somewhere in your code... var url = Environment.BASE_URL 

这创build了一个单一的环境,可以从你的应用程序范围内的任何地方访问。 你必须从使用环境variables的任何组件明确地require(...)模块,但这是一件好事。

我发现最简单的(不是最好的理想的 )解决scheme是使用react-native-dotenv 。 您只需将“react-native-dotenv”预设添加到项目根目录下的.babelrc文件中,如下所示:

 { "presets": ["react-native", "react-native-dotenv"] } 

创build一个.env文件并添加属性:

 echo "SOMETHING=anything" > .env 

然后在你的项目(JS)中:

 import { SOMETHING } from 'react-native-dotenv' console.log(SOMETHING) // "anything" 

在我看来,最好的select是使用react-native-config 。 它支持12个因素 。

我发现这个软件包非常有用。 您可以设置多个环境,例如开发,分期,生产。

在Android的情况下,也可以在Java类,gradle,AndroidManifest.xml等中使用variables。对于iOS,variables也可以在Obj-C类Info.plist中使用。

你只是像创build文件

  • .env.development
  • .env.staging
  • .env.production

你用这些键填充这些文件,例如

 API_URL=https://myapi.com GOOGLE_MAPS_API_KEY=abcdefgh 

然后使用它:

 import Config from 'react-native-config' Config.API_URL // 'https://myapi.com' Config.GOOGLE_MAPS_API_KEY // 'abcdefgh' 

如果你想使用不同的环境,你基本上这样设置ENVFILEvariables:

 ENVFILE=.env.staging react-native run-android 

或组装应用程序的生产(Android在我的情况):

 cd android && ENVFILE=.env.production ./gradlew assembleRelease 

用于设置环境variables的具体方法会因您使用的CI服务,构build方法,平台和工具而异。

如果您使用Buddybuild for CI构build应用程序并pipe理环境variables ,并且需要从JS访问configuration, env.js.example使用键(具有空string值)创buildenv.js.example ,以便签入到源代码pipe理,以及使用Buddybuild在生成时生成一个env.js文件,在post-clone步骤中隐藏构build日志中的文件内容,如下所示:

 #!/usr/bin/env bash ENVJS_FILE="$BUDDYBUILD_WORKSPACE/env.js" # Echo what's happening to the build logs echo Creating environment config file # Create `env.js` file in project root touch $ENVJS_FILE # Write environment config to file, hiding from build logs tee $ENVJS_FILE > /dev/null <<EOF module.exports = { AUTH0_CLIENT_ID: '$AUTH0_CLIENT_ID', AUTH0_DOMAIN: '$AUTH0_DOMAIN' } EOF 

提示:不要忘记将env.js添加到.gitignore以免在开发过程中意外地将configuration和机密检入源代码pipe理。

然后,您可以使用Buddybuildvariables(如BUDDYBUILD_VARIANTS )来pipe理文件的写入方式,以便更好地控制在BUDDYBUILD_VARIANTS如何生成configuration文件。

为了解决这个问题,我使用了__DEV__ -in-native的__DEV__ 。 只要你没有build立自己的生产反应,它就会自动设置为true

例如:

 //vars.js let url, publicKey; if (__DEV__) { url = ... publicKey = ... } else { url = ... publicKey = ... } export {url, publicKey} 

然后,只需import {url} from '../vars' ,您将始终得到正确的一个。 不幸的是,如果你想要两个以上的环境,这将无法正常工作,但它很简单,并且不涉及向项目添加更多的依赖关系。

我认为像下面的库可以帮助你解决这个难题的getPlatform()函数。

https://github.com/joeferraro/react-native-env

 const EnvironmentManager = require('react-native-env'); // read an environment variable from React Native EnvironmentManager.get('SOME_VARIABLE') .then(val => { console.log('value of SOME_VARIABLE is: ', val); }) .catch(err => { console.error('womp womp: ', err.message); }); 

我看到的唯一的问题是,它是asynchronous代码。 有一个pull请求来支持getSync。 检查出来。

https://github.com/joeferraro/react-native-env/pull/9

我使用了babel-plugin-transform-inline-environment-variables。

我所做的是在S3中将configuration文件放入我的不同环境中。

 s3://example-bucket/dev-env.sh s3://example-bucket/prod-env.sh s3://example-bucket/stage-env.sh 

每个环境文件:

 FIRSTENV=FIRSTVALUE SECONDENV=SECONDVALUE 

之后,我在package.json中添加了一个新脚本,该脚本运行捆绑脚本

 if [ "$ENV" == "production" ] then eval $(aws s3 cp s3://example-bucket/prod-env.sh - | sed 's/^/export /') elif [ "$ENV" == "staging" ] then eval $(aws s3 cp s3://example-bucket/stage-env.sh - | sed 's/^/export /') else eval $(aws s3 cp s3://example-bucket/development-env.sh - | sed 's/^/export /') fi react-native start 

在你的应用程序中,你可能会有一个configuration文件:

 const FIRSTENV = process.env['FIRSTENV'] const SECONDENV = process.env['SECONDENV'] 

这将被babel取代:

 const FIRSTENV = 'FIRSTVALUE' const SECONDENV = 'SECONDVALUE' 

记住你必须使用process.env ['STRING']不是process.env.STRING,否则将不能正确转换。

我已经为同样的问题创build了一个预生成脚本,因为我需要一些不同的API端点为不同的环境

 const fs = require('fs') let endPoint if (process.env.MY_ENV === 'dev') { endPoint = 'http://my-api-dev/api/v1' } else if (process.env.MY_ENV === 'test') { endPoint = 'http://127.0.0.1:7001' } else { endPoint = 'http://my-api-pro/api/v1' } let template = ` export default { API_URL: '${endPoint}', DEVICE_FINGERPRINT: Math.random().toString(36).slice(2) } ` fs.writeFile('./src/constants/config.js', template, function (err) { if (err) { return console.log(err) } console.log('Configuration file has generated') }) 

而且我已经创build了一个自定义npm run scripts来执行react-native run ..

我的包-JSON

 "scripts": { "start-ios": "node config-generator.js && react-native run-ios", "build-ios": "node config-generator.js && react-native run-ios --configuration Release", "start-android": "node config-generator.js && react-native run-android", "build-android": "node config-generator.js && cd android/ && ./gradlew assembleRelease", ... } 

然后在我的服务组件中简单地导入自动生成的文件:

 import config from '../constants/config' fetch(`${config.API_URL}/login`, params) 

你也可以有不同的env脚本:production.env.sh development.env.sh production.env.sh

然后在开始工作时将它们源代码(这只是绑定到一个别名),因此所有的sh文件都会为每个envvariables导出:

 export SOME_VAR=1234 export SOME_OTHER=abc 

然后添加babel-plugin-transform-inline-environment-variables将允许在代码中访问它们:

 export const SOME_VAR: ?string = process.env.SOME_VAR; export const SOME_OTHER: ?string = process.env.SOME_OTHER; 

@ chapinkapa的答案是好的。 自从Mobile Center不支持环境variables以来,我采取的一种方法是通过本机模块公开构buildconfiguration:

在android上:

  @Override public Map<String, Object> getConstants() { final Map<String, Object> constants = new HashMap<>(); String buildConfig = BuildConfig.BUILD_TYPE.toLowerCase(); constants.put("ENVIRONMENT", buildConfig); return constants; } 

或在ios上:

  override func constantsToExport() -> [String: Any]! { // debug/ staging / release // on android, I can tell the build config used, but here I use bundle name let STAGING = "staging" let DEBUG = "debug" var environment = "release" if let bundleIdentifier: String = Bundle.main.bundleIdentifier { if (bundleIdentifier.lowercased().hasSuffix(STAGING)) { environment = STAGING } else if (bundleIdentifier.lowercased().hasSuffix(DEBUG)){ environment = DEBUG } } return ["ENVIRONMENT": environment] } 

您可以同步阅读构buildconfiguration,并在Javascript中决定如何行事。