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

例子:

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

当前回答

遵循以下步骤

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'];

欢呼:)

其他回答

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

在我看来,最好的选择是使用react-native-config。 支持12因子。

我发现这个包非常有用。您可以设置多个环境,例如开发、登台、生产。

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

你只需要创建文件

.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'

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

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

或者为生产组装应用程序(在我的情况下是android):

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

经过长时间的努力,我意识到react-native并没有正式提供这个功能。这是在babel生态系统中,所以我应该学习如何写一个babel插件…

/**
 * A simple replace text plugin in babel, such as `webpack.DefinePlugin`
 * 
 * Docs: https://github.com/jamiebuilds/babel-handbook
 */
function definePlugin({ types: t }) {
    const regExclude = /node_modules/;
    return {
        visitor: {
            Identifier(path, state) {
                const { node, parent, scope } = path;
                const { filename, opts } = state;
                const key = node.name;
                const value = opts[key];

                if (key === 'constructor' || value === undefined) { // don't replace
                    return;
                }
                if (t.isMemberExpression(parent)) { // not {"__DEV__":name}
                    return;
                }
                if (t.isObjectProperty(parent) && parent.value !== node) { // error
                    return;
                }
                if (scope.getBinding(key)) { // should in global
                    return;
                }
                if (regExclude.test(filename)) { // exclude node_modules
                    return;
                }
                switch (typeof value) {
                    case 'boolean':
                        path.replaceWith(t.booleanLiteral(value));
                        break;
                    case 'string':
                        path.replaceWith(t.stringLiteral(value));
                        break;
                    default:
                        console.warn('definePlugin only support string/boolean, so `%s` will not be replaced', key);
                        break;
                }
            },
        },
    };
}

module.exports = definePlugin;

就这样,然后你可以这样用:

module.exports = {
    presets: [],
    plugins: [
        [require('./definePlugin.js'), {
            // your environments...
            __DEV__: true,
            __URL__: 'https://example.org',
        }],
    ],
};

回答者提到的包也很棒,我也参考了metro-transform-plugins/src/inline-plugin.js。

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

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

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

每个env文件:

FIRSTENV=FIRSTVALUE
SECONDENV=SECONDVALUE

之后,我在包中添加了一个新脚本。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

在你的应用中,你可能会有一个配置文件,它有:

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

它将被巴别塔所取代:

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

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

嗨,如果你正面临这个问题,试试这个,这对我有用,以后谢谢我

在bable.js

 plugins: [
      [
        "module:react-native-dotenv",
        {
          moduleName: "react-native-dotenv",
        },
      ],
    ],

use

import { YOURAPIKEY } from "react-native-dotenv";


inseted  of

import { YOURAPIKEY } from "@env";