Установка переменной среды в react-native?



Я использую react-native для создания кросс-платформенного приложения, но я не знаю, как установить переменную среды, чтобы у меня были разные константы для разных сред.



пример:



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

13 ответов:

вместо жесткого кодирования ваших констант приложения и выполнения переключения на окружающую среду (я объясню, как это сделать через мгновение), я предлагаю использовать двенадцать фактор предложение о том, чтобы ваш процесс сборки определял ваш BASE_URL и свой API_KEY.

чтобы ответить, как выставить свою среду react-native, Я предлагаю использовать Бабеля babel-plugin-transform-inline-environment-variables.

чтобы получить эту работу вам нужно скачать плагин и тогда вам нужно будет настроить .babelrc и это должно выглядеть примерно так:

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

и поэтому, если вы транспилируете свой собственный код react, запустив API_KEY=my-app-id react-native bundle (или start, run-ios, или run-android) тогда все, что вам нужно сделать, это чтобы ваш код выглядел так:

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

и тогда Бабель заменит это:

const apiKey = 'my-app-id';

надеюсь, что это помогает!

самый простой (не лучшие или идеал) решение я нашел, было использовать react-native-dotenv. Вы просто добавляете предустановку "react-native-dotenv" в свой .babelrc файл в корне проекта вот так:

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

создать .env файл и добавить свойства:

echo "SOMETHING=anything" > .env

затем в вашем проекте (JS):

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

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

это создает синглтон среда, к которой можно получить доступ из любого места в области вашего приложения. Вы должны явно require(...) модуль из любых компонентов, которые используют переменные среды,но это хорошо.

на мой взгляд, лучший вариант-использовать реагировать родной конфиг. Он поддерживает 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

я использовал __DEV__ полифилл, который встроен в react-native для решения этой проблемы. Он автоматически устанавливается в true пока вы не строите react native для производства.

например:

//vars.js

let url, publicKey;
if (__DEV__) {
  url = ...
  publicKey = ...
} else {
  url = ...
  publicKey = ...
}

export {url, publicKey}

потом просто import {url} from '../vars'и вы всегда сможете сделать правильный. К сожалению, это не будет работать, если вы хотите более двух сред, но это легко и не требует добавления дополнительных зависимостей к вашему проекту.

конкретный метод, используемый для установки переменных среды, будет зависеть от службы CI, подхода к построению, платформы и инструментов, которые вы используете.

если вы используете Buddybuild для CI для создания приложения и управление переменными окружения, и вам нужен доступ к конфигурации из JS, создать env.js.example С ключами (с пустыми строковыми значениями) для регистрации в системе управления версиями и использования Buddybuild для создания env.js файл во время сборки в post-clone шаг, скрывая содержимое файла от журналы сборки, например:

#!/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 таким образом, конфигурация и секреты не проверяются в системе управления версиями случайно во время разработки.

затем вы можете управлять тем, как файл записывается с помощью переменные Buddybuild как BUDDYBUILD_VARIANTS, например, чтобы получить больший контроль над тем, как ваша конфигурация создается во время сборки.

Я думаю, что что-то вроде следующей библиотеки может помочь вам решить недостающий бит головоломки, функцию 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);
  });

единственная проблема, которую я вижу с этим, что это асинхронный код. Существует запрос на вытягивание для поддержки getSync. Проверьте это тоже.

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

я использую 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'] не обрабатывать.ОКР.Строка или она не будет преобразована должным образом.

Я создал сценарий предварительной сборки для той же проблемы, потому что мне нужны некоторые конечные точки api differents для различных сред

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

можно получить доступ к переменным с process.env.blabla вместо process.env['blabla']. Недавно я заставил его работать и прокомментировал, как я это сделал по проблеме на GitHub, потому что у меня были некоторые проблемы с кэшем на основе принятого ответа. здесь - это вопрос.

вы также можете иметь различные сценарии 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, как вы собираетесь вести себя.

Шаг 1: создайте отдельный компонент, как это Имя компонента:pagebase.js
Шаг 2: внутри этого используйте код

    export const BASE_URL = "http://192.168.10.10:4848/";
    export const API_KEY = 'key_token';

Шаг 3: Используйте его в любом компоненте, для его использования сначала импортируйте этот компонент, а затем используйте его. Импортируйте его и используйте:

        import * as base from "./pagebase";

        base.BASE_URL
        base.API_KEY

Comments

    Ничего не найдено.