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

例子:

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

当前回答

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

然后在开始工作时将它们来源[这只是绑定到一个别名] 所以所有的sh文件都导出了每个env变量:

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不支持环境变量,我采取的一种方法是通过本地模块公开构建配置:

在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]
  }

您可以同步读取构建配置,并在Javascript中决定如何执行。

我发现最简单(不是最好或最理想)的解决方案是使用react-native-dotenv。你只需在你的.babelrc文件的根目录下添加"react-native-dotenv"预设,如下所示:

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

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

echo "SOMETHING=anything" > .env

然后在你的项目(JS):

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

遵循以下步骤

NPM安装react-native-dotenv 用一些变量名设置。env文件,例如APP_NAME="my-app" 修改bable.config.js

模块。出口= { 预设:['模块:metro-react-native-babel-preset '), 插件:[ ["模块:react-native-dotenv ", { :“envName APP_ENV”, :“moduleName @env”, “路径”:“.env”, “安全”:假的, “allowUndefined”:没错, “详细”:假的 }) ] };

重新启动所有应用程序 尝试从“@env”导入{APP_NAME}。如果这不起作用,那么执行这个const APP_NAME = process.env['APP_NAME'];

欢呼:)

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

但是,有时您需要组件能够感知它们所处的环境。在这种情况下,定义一个环境模块非常简单,然后组件可以调用它来获取环境变量,例如:

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 (e.g. staging, production, etc)
    var platform = getPlatform()

    // ...now return the correct environment
    return _Environments[platform]
}

var Environment = getEnvironment()
module.exports = Environment

my-component.js

var Environment = require('./environment.js')

...somewhere in your code...
var url = Environment.BASE_URL

这创建了一个单例环境,可以从应用范围内的任何地方访问。你必须显式地要求(…)使用环境变量的任何组件的模块,但这是一件好事。

我已经为相同的问题创建了一个预构建脚本,因为我需要一些不同环境的不同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')
})

我已经创建了一个自定义的npm运行脚本来执行反应本机运行..

我package-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)