반응 네이티브에서 환경 변수를 설정합니까?


152

크로스 플랫폼 앱을 만들기 위해 react-native를 사용하고 있지만 환경에 따라 다른 상수를 가질 수 있도록 환경 변수를 설정하는 방법을 모릅니다.

예:

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

당신은 이것을 시도 할 수 있습니다import {Platform} from 'react-native'; console.log(Platform);
Praveen Prasad

답변:


138

대신 앱 상수를 하드 코딩 및 환경에 스위치를하는, 내가 사용하는 것이 좋습니다 (나는 순간에 그 작업을 수행하는 방법을 설명 할 것이다) 열두 요소의 빌드 프로세스를 갖는 제안을 당신의 정의 BASE_URL와를 API_KEY.

환경을 노출시키는 방법에 대답하려면 react-nativeBabel의 babel-plugin-transform-inline-environment-variables를 사용하는 것이 좋습니다 .

이 작업을 수행하려면 플러그인을 다운로드 한 다음 a를 설정 .babelrc해야하며 다음과 같이 표시되어야합니다.

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

따라서 실행 API_KEY=my-app-id react-native bundle(또는 start, run-ios 또는 run-android)을 실행 하여 반응 네이티브 코드를 변환 하면 코드를 다음과 같이하면됩니다.

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

그리고 바벨은 이것을 다음으로 대체 할 것입니다.

const apiKey = 'my-app-id';

도움이 되었기를 바랍니다!


7
훌륭한 솔루션처럼 들리지만 RN@0.37.0에서 작동하지 않습니다. 에 대한 유일한 속성은 process.env입니다 NODE_ENV.
Adam Faryna

2
Jack Zheng의 아래 답변을 참조하십시오 process.env.API_KEY... process.env['API_KEY']대신 변수를 사용할 수 없습니다 ... 대신 사용하십시오
Steven Yap

6
process.env [ 'API_KEY']가 정의되지 않은 것으로 나타납니다. 누구나 나를 도와 줄 수 있습니까
user1106888

2
나는 같은 문제가 있었다 : undefined
Guto Marrara Marzagao

7
v0.56에서 작동합니다. react-native start --reset-cache환경 변수를 변경할 때마다 실행 하여 번 들러의 캐시를 지워야 합니다.
soheilpro

55

내가 찾은 가장 간단한 ( 최상의 또는 이상적이지 않은 ) 솔루션은 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"

1
.env 기반 솔루션을 원했습니다. 감사합니다!
Anshul Koka

3
@Slavo Vojacek 어떻게 내가 예를 하나 구성이 어떻게 사용합니까 base_url모두 stagingproduction?
Compaq LE2202x

@ CompaqLE2202x 잘 모르겠습니다. .env환경에 따라 다른 파일을 사용 하거나 다른 파일 에서 일부 값을 재사용하는 것에 대해 질문 .env하고 있으므로 스테이징 및 프로덕션과 같이 파일을 복제하지 않습니까?
Slavo Vojacek

5
@SlavoVojacek 나는 다른에 대해 부탁 해요 .env환경에 따라 파일하자의 말 stagingproduction.
Compaq LE2202x 2014 년

@SlavoVojacek은 CI 단계 또는 배포시 값을 덮어 쓸 수 없습니까?
mgamsjager

37

제 생각에는 가장 좋은 옵션은 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

9
README 에서이 모듈은 패키징을위한 비밀을 난독 화하거나 암호화하지 않으므로 중요한 키는 .env에 저장하지 마십시오. 기본적으로 사용자가 모바일 앱 비밀을 리버스 엔지니어링하는 것을 방지하는 것은 불가능하므로이를 염두에두고 앱 (및 API)을 디자인하십시오
Marklar

것입니다 그 것이다 .env의에서 그들에게 com.twitter.sdk.android.CONSUMER_KEY로 키 세트를 가질 필요 트위터 같은 일부 프레임 워크와 함께하지 작업
의 Thibaut 노아

매니페스트 안에 키를 넣는 것을 의미한다면 확장 프로그램이이를 지원합니다. 이 답변에는 설명되어 있지 않습니다. XML, Java 및 JS 파일에서 변수를 사용할 수 있습니다.
sfratini

4
react-native-config는 RN 0.56에서 작동하지 않으며, 해결되지 않은 문제가 있으며 6 개월 이상 유지되지 않습니다. 문제 마녀 RN에서의 사용은 사망 github.com/luggit/react-native-config/issues/267 여기에, 일부는 작동하도록 해킹되어 github.com/luggit/react-native-config/issues/285을
Marecky을

24

반응 네이티브에는 전역 변수라는 개념이 없습니다. 컴포넌트 모듈 성과 재사용 성을 높이기 위해 모듈 식 범위를 엄격하게 적용 합니다.

그러나 때로는 환경을 인식하기 위해 구성 요소가 필요합니다. 이 경우 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

my-component.js

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

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

이렇게하면 앱 범위 내 어디에서나 액세스 할 수 있는 싱글 톤 환경 이 만들어집니다 . require(...)환경 변수를 사용하는 모든 구성 요소에서 모듈 을 명시 적으로 지정 해야하지만 좋은 것입니다.


19
내 문제는 방법 getPlatform()입니다. 나는이 같은 파일을 가지고 있지만 여기에 논리를 완료 원주민 반응하지 수
데이먼 위안

@DamonYuan은 패키지 설정 방법에 전적으로 의존합니다. 내가 무슨 생각이 없다 staging또는 production사용자 환경에 따라 때문에, 심지어 평균을. 예를 들어, IOS와 Android에 대해 다른 특징을 원할 경우 환경 index.ios.jsindex.android.js파일 을 가져 와서 플랫폼을 설정하여 환경을 초기화 할 수 있습니다 ( 예 :) Environment.initialize('android').
tohster

@DamonYuan 내가 도움을 준 것이 있습니까? 아니면 더 설명이 필요하십니까?
chapinkapa

코드를 제어 할 때 매우 좋습니다. 저는 process.env에 의존하는 세 번째 부분 모듈을 실행하고 있습니다.
enapupe

2
env.js파일 을 작성하는 경우 체크인에서 저장소 로 파일을 무시하고 비어있는 문자열 값과 함께 사용 된 키를 env.js.example체크인하는 다른 파일 로 복사하여 다른 사용자가 앱을 더 쉽게 빌드 할 수 있도록하십시오. 실수로 프로젝트 시크릿을 체크인 하는 경우 소스에서뿐만 아니라 히스토리에서도 제거하기 위해 히스토리다시 작성 하는 것이 좋습니다.
Josh Habdas

17

__DEV__이 문제를 해결하기 위해 반응 네이티브에 내장 된 폴리 필을 사용했습니다 . true프로덕션 용 기본 반응을 작성하지 않는 한 자동으로 설정됩니다 .

예 :

//vars.js

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

export {url, publicKey}

그런 다음 import {url} from '../vars'항상 올바른 것을 얻을 수 있습니다. 불행히도, 둘 이상의 환경을 원할 경우 작동하지 않지만 쉽고 간단하며 프로젝트에 더 많은 종속성을 추가하지 않습니다.


xcode에서 릴리스 빌드를 생성 할 때에도 DEV 를 '포커스'하는 방법을 알고 있습니까?
realtebo

1
아니. 방금 prod vars를 주석 처리 한 다음 dev 변수로 릴리스 빌드를 수행 할 때 dev vars를 prod 섹션에 복사하여 붙여 넣습니다.
Logister

1
나는 이것이 가장 우아한 해결
책임을 알았다

5

환경 변수를 설정하는 데 사용되는 특정 방법은 사용중인 CI 서비스, 빌드 방식, 플랫폼 및 도구에 따라 다릅니다.

CI 용 Buddybuild를 사용하여 앱을 빌드 하고 환경 변수를 관리 하고 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빌드시 구성이 생성되는 방식을보다 효과적으로 제어 할 수 있습니다.


전반적으로 나는 아이디어를 좋아하지만 env.js.example부품 은 어떻게 작동합니까? 로컬 환경에서 앱을 시작하고 싶다고 가정 해 봅시다. 내 경우 env.js파일이 gitignore에 있고 env.js.example아웃 라인으로 사용하는 경우,이 env.js.example난 그냥 조금이 부분에 의해 무엇을 의미하는지에 혼란 스러워요, 그래서 합법적 인 JS 확장되지 않습니다
볼크

@volk이 env.js.example파일은 코드베이스에 참조 문서로서, 앱이 어떤 구성 키를 사용하고자 하는가에 대한 정식 소스입니다. 앱을 실행하는 데 필요한 키와 한 번 복사하고 이름을 바꾼 파일 이름을 설명합니다. 패턴은 패턴을 들어 올린 dotenv gem을 사용하는 Ruby 앱에서 일반적입니다 .
Josh Habdas

3

나는 다음과 같은 라이브러리가 퍼즐의 누락 된 비트 인 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


3
언급되지 않은 대체 방법을 제공하도록 찬성했습니다. 하나의 크기는 모두 적합하지 않습니다.
Josh Habdas

비동기 풀 요청이 다음에 합병되었습니다 :
jcollum

5
react-native-env가 Android를 지원하지 않는 것 같습니다. 점은 무엇인가?
jcollum

3

다른 환경에 대해 다른 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 을 실행 하는 사용자 지정 을 만들었습니다 .

내 패키지 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)

3

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

2

나는 사용한다 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']NOT 을 사용해야 process.env.STRING합니다. 그렇지 않으면 제대로 변환되지 않습니다.


REMEMBER you have to use process.env['STRING'] NOT process.env.STRING or it won't convert properly.감사! 이것은 나를 여행하는 사람이다! !!
Steven Yap

1

[출처] 내가 찾은 것으로부터, 기본적으로 보이는 것처럼, 프로덕션 및 개발 구성 만 할 수 있습니다 (스테이징 또는 기타 환경 없음) – 맞습니까?

지금은 엑스포 릴리스 채널을 감지하고 그에 따라 반환 된 변수를 변경하는 데 사용할 수있는 environment.js 파일을 사용하고 있지만 빌드 를 위해 준비되지 않은 DEV 변수 를 업데이트해야합니다. 찌르다:

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;

대안

누구나 엑스포로 빌드 된 프로젝트에 react-native-dotenv 사용 경험이 있습니까? 당신의 생각을 듣고 싶습니다

https://github.com/zetachang/react-native-dotenv


릴리스 채널 이름을 원하는만큼 정의하고 환경 변수를 정의하기 위해 이름을 테스트 할 수 있습니다. 여기서 제한 사항은 releaseChannel이 정의되지 않은 dev 환경에 있습니다. 따라서 babel-plugin-transform-inline-environment-variables를 사용할 수 있습니다. 스크립트에서 환경 변수를 전달하고 dev.en 파일에서 environment.js 파일의 process.env [ 'VAR_NAME']을 참조 할 수 있습니까?
colemerrick

0

다른 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 님이 말하지 않은 것을 추가하고 있습니까?
Maximo Dominguez

0

@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에서 동작 방식을 결정할 수 있습니다.


0

process.env.blabla대신에 변수에 액세스 할 수 있습니다 process.env['blabla']. 나는 최근에 그것을 작동시키고 GitHub의 문제에서 어떻게했는지에 대해 논평했습니다. 허용 된 답변을 기반으로 캐시에 문제가 있었기 때문입니다. 여기 에 문제가 있습니다.


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.