Установка переменной среды в реакции-родной?
Я использую response-native для создания кросс-платформенного приложения, но я не знаю, как установить переменную среды, чтобы я мог иметь разные константы для разных сред.
Пример:
development:
BASE_URL: '',
API_KEY: '',
staging:
BASE_URL: '',
API_KEY: '',
production:
BASE_URL: '',
API_KEY: '',
Ответы
Ответ 1
Вместо жесткого кодирования ваших констант приложения и включения среды (я объясню, как это сделать в данный момент), я предлагаю использовать двенадцать факторов, чтобы ваш процесс сборки определял ваш BASE_URL
и ваш API_KEY
.
Чтобы ответить, как выставить свою среду в react-native
, я предлагаю использовать Babel babel-plugin-transform-inline-environment-variables.
Чтобы получить эту работу, вам нужно загрузить плагин, а затем вам нужно настроить .babelrc
, и он должен выглядеть примерно так:
{
"presets": ["react-native"],
"plugins": [
"transform-inline-environment-variables"
]
}
Итак, если вы перекроете свой реактивный код, запустив API_KEY=my-app-id react-native bundle
(или запустите, запустите ios или run-android), вам нужно всего лишь сделать код:
const apiKey = process.env['API_KEY'];
И тогда Бабель заменит это:
const apiKey = 'my-app-id';
Надеюсь, это поможет!
Ответ 2
Самое простое (не лучшее или идеальное) решение, которое я нашел, это использовать 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"
Ответ 3
На мой взгляд, лучшим вариантом является использование 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
или для сборки приложения для производства (андроид в моем случае):
cd android && ENVFILE=.env.production ./gradlew assembleRelease
Ответ 4
React native не имеет понятия глобальных переменных.
Он строго соблюдает модульную область, чтобы повысить модульность компонентов и возможность повторного использования.
Иногда, однако, вам нужны компоненты, которые должны знать об окружающей среде. В этом случае очень просто определить модуль Environment
, который компоненты могут затем вызвать для получения переменных среды, например:
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
мой-component.js
var Environment = require('./environment.js')
...somewhere in your code...
var url = Environment.BASE_URL
Это создает среду singleton, к которой можно получить доступ из любой точки вашего приложения. Вы должны явно указать require(...)
модуль из любых компонентов, которые используют переменные среды, но это хорошо.
Ответ 5
Я использовал __DEV__
polyfill, который встроен в реакцию-native, чтобы решить эту проблему. Он автоматически устанавливается на true
, пока вы не строите реакцию на родной для производства.
Например:
//vars.js
let url, publicKey;
if (__DEV__) {
url = ...
publicKey = ...
} else {
url = ...
publicKey = ...
}
export {url, publicKey}
Затем просто import {url} from '../vars'
, и вы всегда получите правильный. К сожалению, это не будет работать, если вы хотите более двух сред, но это легко и не требует добавления дополнительных зависимостей к вашему проекту.
Ответ 6
Конкретный метод, используемый для установки переменных среды, зависит от службы CI, подхода к сборке, платформы и инструментов, которые вы используете.
Если вы используете Buddybuild for CI для создания приложения и управления переменными среды, и вам нужен доступ к конфигурации из JS, создайте env.js.example
с ключами (с пустыми строковыми значениями) для регистрации в системе контроля env.js.example
и Используйте Buddybuild для создания файла env.js
во время сборки на этапе post-clone
, скрывая содержимое файла из журналов сборки, например, так:
#!/usr/bin/env bash
ENVJS_FILE="$BUDDYBUILD_WORKSPACE/env.js"
# Echo what 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
чтобы настройки и секреты не env.js
в .gitignore
env.js
.gitignore
случайно при разработке.
Затем вы можете управлять тем, как файл будет записан, используя переменные BUDDYBUILD_VARIANTS
, например, BUDDYBUILD_VARIANTS
, чтобы получить больший контроль над тем, как создается ваша конфигурация во время сборки.
Ответ 7
Я думаю, что что-то вроде следующей библиотеки может помочь вам решить недостающий бит головоломки - функцию 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
Ответ 8
Я создал предварительную сборку script для той же самой проблемы, потому что мне нужны некоторые разные точки 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 run scripts
, чтобы выполнить run-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)
Ответ 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
После этого я добавил новый скрипт в мой 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
В вашем приложении вы, вероятно, будете иметь файл конфигурации, который имеет:
const FIRSTENV = process.env['FIRSTENV']
const SECONDENV = process.env['SECONDENV']
который будет заменен на babel:
const FIRSTENV = 'FIRSTVALUE'
const SECONDENV = 'SECONDVALUE'
ПОМНИТЕ, что вы должны использовать process.env['STRING']
НЕ process.env.STRING
иначе он не будет преобразован должным образом.
Ответ 10
[Источник] Из того, что я обнаружил, похоже, что по умолчанию можно выполнять только конфигурации для производства и разработки (без промежуточных или других сред) - это правильно?
Прямо сейчас я использую файл environment.js, который можно использовать для обнаружения каналов выпуска expo и изменения возвращаемых переменных, основываясь на этом, но для сборки мне нужно обновить переменную DEV non-, возвращаемую в качестве промежуточной или продукт:
import { Constants } from 'expo';
import { Platform } from 'react-native';
const localhost = Platform.OS === 'ios' ? 'http://localhost:4000/' : 'http://10.0.2.2:4000/';
const ENV = {
dev: {
apiUrl: localhost,
},
staging: {
apiUrl: 'https://your-staging-api-url-here.com/'
},
prod: {
apiUrl: 'https://your-prod-api-url-here.com/'
},
}
const getEnvVars = (env = Constants.manifest.releaseChannel) => {
// What is __DEV__ ?
// This variable is set to true when react-native is running in Dev mode.
// __DEV__ is true when run locally, but false when published.
if (__DEV__) {
return ENV.dev;
} else {
// When publishing to production, change this to 'ENV.prod' before running an 'expo build'
return ENV.staging;
}
}
export default getEnvVars;
альтернативы
у кого-нибудь есть опыт использования response-native-dotenv для проектов, построенных с помощью expo? Я хотел бы услышать ваши мысли
https://github.com/zetachang/react-native-dotenv
Ответ 11
у вас также могут быть разные сценарии 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 позволит получить доступ к ним в коде:
export const SOME_VAR: ?string = process.env.SOME_VAR;
export const SOME_OTHER: ?string = process.env.SOME_OTHER;
Ответ 12
@chapinkapa ответ хороший. Подход, который я предпринял после того, как Mobile Center не поддерживает переменные среды, заключается в том, чтобы разоблачить конфигурацию сборки через собственный модуль:
В андроиде:
@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, как вы будете себя вести.
Ответ 13
Доступ к переменным можно получить с помощью process.env.blabla
вместо process.env['blabla']
. Недавно я сделал это и прокомментировал, как я это сделал по проблеме GitHub, потому что у меня были проблемы с кешем на основе принятого ответа. Здесь является проблема.
Ответ 14
Шаг 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
Ответ 15
Для последних версий RN вы можете использовать этот собственный модуль: https://github.com/luggit/react-native-config