Установка переменной среды в react-native?
Я использую react-native для создания кросс-платформенного приложения, но я не знаю, как установить переменную среды, чтобы у меня были разные константы для разных сред.
пример:
development:
BASE_URL: '',
API_KEY: '',
staging:
BASE_URL: '',
API_KEY: '',
production:
BASE_URL: '',
API_KEY: '',
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 = Environmentmy-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. Проверьте это тоже.
я использую 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