React-native içinde ortam değişkeni ayarlanıyor mu?


160

Platformlar arası bir uygulama oluşturmak için react-native kullanıyorum, ancak farklı ortamlar için farklı sabitlere sahip olabilmek için ortam değişkenini nasıl ayarlayacağımı bilmiyorum.

Misal:

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

bunu deneyebilirsinizimport {Platform} from 'react-native'; console.log(Platform);
Praveen Prasad

Yanıtlar:


146

Bunun yerine, uygulama sabitleri sabit kodlama ve çevre üzerinde anahtarı yapmanın, ben kullanmanızı öneririz (birazdan bunu nasıl açıklayacağız) oniki faktör sizin derleme işlemi sahip öneri senin tanımlamak BASE_URLve keşfetmenize API_KEY.

Ortamınızı nasıl açığa çıkaracağınıza cevap vermek için Babel'in babel-plugin-transform-inline-ortam-değişkenlerinireact-native kullanmanızı öneririm .

Bu çalışmayı sağlamak için eklentiyi indirmeniz ve ardından a kurmanız gerekecek .babelrcve şunun gibi görünmesi gerekir:

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

Ve böylece, react-native kodunuzu çalıştırarak API_KEY=my-app-id react-native bundle(veya start, run-ios veya run-android) aktarırsanız, yapmanız gereken tek şey kodunuzun şöyle görünmesini sağlamaktır:

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

Ve sonra Babel bunu şu şekilde değiştirecek:

const apiKey = 'my-app-id';

Bu yardımcı olur umarım!


7
Harika bir çözüm gibi görünüyor, ancak benim için RN@0.37.0'da çalışmıyor. Sadece mülkiyet üzerinde process.envolduğunu NODE_ENV.
Adam Faryna

3
Jack Zheng'in aşağıdaki cevabına bakın ... değişkene şu yolla erişemezsiniz process.env.API_KEY... process.env['API_KEY']bunun yerine kullanın
Steven Yap

6
Process.env ['API_KEY'] 'i tanımsız olarak alıyorum. Biri bunu ayarlamama yardım edebilir mi
user1106888

2
Aynı sorunu yaşadım: tanımsız
Guto Marrara Marzagao

7
Benim için v0.56'da çalışıyor. react-native start --reset-cacheOrtam değişkenlerini her değiştirdiğinizde çalıştırarak paketleyicinin önbelleğini temizlemeniz gerekir .
soheilpro

57

Bulduğum en basit (en iyi veya ideal değil ) çözüm, react-native-dotenv kullanmaktı . "React-native-dotenv" ön ayarını, .babelrcşu şekilde proje kökünde dosyanıza eklemeniz yeterlidir :

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

Bir .envdosya oluşturun ve özellikler ekleyin:

echo "SOMETHING=anything" > .env

Sonra projenizde (JS):

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

1
.Env tabanlı bir çözüm umuyordum. Teşekkür ederim!
Anshul Koka

3
@Slavo Vojacek Örneğin birini base_urlhem stagingve hem de için yapılandırmak için bunu nasıl kullanabilirim production?
Compaq LE2202x

@ CompaqLE2202x Anladığımdan pek emin değilim? Farklı .envdosyalar (ortam başına) kullanmayı mı , yoksa bazı değerlerinizi farklı .envdosyalarda yeniden kullanmayı mı soruyorsunuz , böylece onları örneğin Aşama ve Üretim genelinde kopyalamayacaksınız?
Slavo Vojacek

6
@SlavoVojacek .envHer ortam için farklı dosyalar soruyorum stagingve diyelim production.
Compaq LE2202x

@SlavoVojacek bir CI aşamasında veya dağıtımda değerlerin üzerine yazamaz mısın?
mgamsjager

43

Kanımca en iyi seçenek react-native-config kullanmaktır . 12 faktörü destekler .

Bu paketi son derece yararlı buldum. Geliştirme, hazırlık, üretim gibi birden çok ortam ayarlayabilirsiniz.

Android olması durumunda, değişkenler Java sınıflarında, gradle, AndroidManifest.xml'de de mevcuttur. İOS durumunda, değişkenler Obj-C sınıflarında, Info.plist'te de mevcuttur.

Sadece şu şekilde dosyalar oluşturursun

  • .env.development
  • .env.staging
  • .env.production

Bu dosyaları anahtar, değerlerle doldurursunuz

API_URL=https://myapi.com
GOOGLE_MAPS_API_KEY=abcdefgh

ve sonra sadece kullanın:

import Config from 'react-native-config'

Config.API_URL  // 'https://myapi.com'
Config.GOOGLE_MAPS_API_KEY  // 'abcdefgh'

Farklı ortamlar kullanmak istiyorsanız, temel olarak ENVFILE değişkenini şu şekilde ayarlarsınız:

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

veya üretim için uygulama montajı için (benim durumumda android):

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

10
README'de belirtilmeye değer olabilir. Bu modülün paketleme için sırları gizlemediğini veya şifrelemediğini, bu nedenle hassas anahtarları .env'de saklamayın. Kullanıcıların mobil uygulama sırlarına ters mühendislik uygulamalarını engellemek temelde imkansızdır, bu nedenle uygulamanızı (ve API'lerinizi) bunu göz önünde bulundurarak tasarlayın
Marklar

Mesele, twitter gibi bazı çerçevelerde çalışmayacak ve .env
thibaut noah

Anahtarı Manifest'in içine koymayı kastediyorsanız, uzantı onu destekler. Bu cevapta açıklanmadı. Değişkenleri XML, Java ve JS dosyalarında kullanabilirsiniz.
sfratini

4
react-native-config, RN 0.56 ile çalışmıyor, çözülmemiş sorunları var ve 6 aydan fazla bir süredir bakımı yapılmıyor. Sorun cadı, RN'deki kullanımını sonlandırıyor github.com/luggit/react-native-config/issues/267 , işte çalışmasını sağlamak için bazı hacklemeler github.com/luggit/react-native-config/issues/285
Marecky

25

React native, global değişkenler kavramına sahip değildir. Bileşenlerin modülerliğini ve yeniden kullanılabilirliğini artırmak için modüler kapsamı sıkı bir şekilde uygular .

Bazen, ortamlarının farkında olmak için bileşenlere ihtiyacınız vardır. Bu durumda, Environmentbileşenlerin daha sonra ortam değişkenlerini almak için çağırabileceği bir modül tanımlamak çok basittir , örneğin:

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

Bu, uygulamanızın kapsamı içinde herhangi bir yerden erişilebilen tek bir ortam oluşturur . require(...)Ortam değişkenlerini kullanan herhangi bir bileşenden modülü açıkça almanız gerekir , ancak bu iyi bir şeydir.


19
benim sorunum nasıl yapılacağı getPlatform(). Bunun gibi bir dosya oluşturdum ama mantığı burada React Native
Damon Yuan'da

@ DamonYuan bu tamamen paketlerinizi nasıl kurduğunuza bağlıdır. Ben hiçbir fikrim yok stagingya productionda ortama bağlı olarak, çünkü bile ortalama. Örneğin, IOS ve Android için farklı tatlar istiyorsanız, Ortamı sizin index.ios.jsve index.android.jsdosyalarınızı içe aktararak ve platformu oraya ayarlayarak başlatabilirsiniz , örn Environment.initialize('android').
tohster

@DamonYuan benim koyduğum yardımı yapıyor mu yoksa daha fazla açıklamaya mı ihtiyacın var?
chapinkapa

Kod üzerinde kontrole sahip olduğunuzda bu çok güzel.
Process.env'ye

2
Bir env.jsdosya oluşturursanız , check-in'lerden depoya yok saydığınızdan ve kullanılan anahtarları boş dize değerleriyle başka bir env.js.exampledosyaya kopyaladığınızdan emin olun , böylece başkalarının uygulamanızı daha kolay oluşturabilmesi için check-in yapın. Yanlışlıkla proje sırlarını kontrol ederseniz, geçmişi yeniden yazarak bunları yalnızca kaynaktan değil geçmişinden de kaldırmayı düşünün .
Josh Habdas

18

__DEV__Bu sorunu çözmek için react-native içine yerleştirilmiş polyfill'i kullandım . trueÜretim için yerel tepki oluşturmadığınız sürece otomatik olarak ayarlanır .

Örneğin:

//vars.js

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

export {url, publicKey}

O zaman sadece import {url} from '../vars've her zaman doğru olanı alacaksınız. Ne yazık ki, ikiden fazla ortam istiyorsanız bu işe yaramayacaktır, ancak kolaydır ve projenize daha fazla bağımlılık eklemeyi gerektirmez.


Eğer 'da darbe' bir yolunu biliyor musunuz DEV xcode bir sürüm derlemesi oluştururken bile TRUE?
realtebo

1
Hayır! Sadece üretim değişkenlerini yorumluyorum ve dev değişkenleri ile bir sürüm derlemesi yapmak istediğimde dev değişkenlerini üretim bölümüne kopyalayıp yapıştırıyorum.
Logister

1
Bunu en zarif çözümü buldum
Dani Sh90

5

Ortam değişkenlerini ayarlamak için kullanılan özel yöntem, CI hizmetine, derleme yaklaşımına, platforma ve kullandığınız araçlara göre değişecektir.

Bir uygulama oluşturmak ve ortam değişkenlerini yönetmek için Buddybuild for CI kullanıyorsanız ve JS'den yapılandırmaya erişmeniz gerekiyorsa, env.js.examplekaynak kontrolüne giriş için anahtarlar (boş dize değerleri ile) oluşturun ve Buddybuild'i kullanarak env.jsdosya oluşturma sırasında post-clonedosya içeriğini derleme günlüklerinden gizleyerek, örneğin:

#!/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

İpucu: eklemeyi unutmayın Do env.jsiçin .gitignoreyapılandırma ve sırları gelişimi sırasında yanlışlıkla Kaynak denetime kontrol edilmez böylece.

Daha sonra kullanarak dosya yazılı alır nasıl yönetebilir Buddybuild değişkenleri gibi BUDDYBUILD_VARIANTSsizin yapılandırma yapı anda üretilir şekli üzerinde daha fazla kontrol etmesine, örneğin,.


Genel olarak bu fikri beğendim, ancak env.js.examplebölüm nasıl işliyor ? diyelim ki uygulamayı yerel ortamımda başlatmak istiyorum. Benim eğer env.jsdosya gitignore olduğunu ve env.js.examplebir taslak olarak kullanılır, env.js.exampleben sadece biraz bu bölümü neyi kastettiğini üzerinde karıştı olduğum bu yüzden, meşru bir JS uzantısı değildir
volk

@volk env.js.exampleDosya kod tabanında, uygulamanın hangi yapılandırma anahtarlarını kullanmak istediği konusunda kanonik bir doğruluk kaynağı olan bir referans belge olarak bulunur. Hem uygulamayı çalıştırmak için gereken anahtarları hem de kopyalandıktan ve yeniden adlandırıldıktan sonra beklenen dosya adını açıklar. Desen, deseni kaldırdığım nokta olan dotenv gem kullanan Ruby uygulamalarında yaygındır .
Josh Habdas

4

Aynı sorun için bir ön derleme komut dosyası oluşturdum çünkü farklı ortamlar için bazı farklı api uç noktalarına ihtiyacım var

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

Ve react-native çalıştırmayınpm run scripts yürütmek için bir özel oluşturdum ..

Benim paket-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",
    ...
}

Ardından, hizmetlerimde bileşenler otomatik olarak oluşturulan dosyayı içe aktarın:

import config from '../constants/config'

fetch(`${config.API_URL}/login`, params)

3

Aşağıdaki kitaplık gibi bir şeyin bulmacanın eksik parçası olan getPlatform () işlevini çözmenize yardımcı olabileceğini düşünüyorum.

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

Bununla ilgili gördüğüm tek sorun, eşzamansız kod olması. GetSync'i desteklemek için bir çekme isteği var. Şuna da bakın.

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


3
Bahsedilmeyen alternatif bir yaklaşım sağladığı için oy verildi. Herkese uyan tek bir beden yoktur.
Josh Habdas


5
react-native-env, Android'i desteklemiyor gibi görünüyor. Amaç ne?
jcollum

3

Adım 1: Bu Bileşen adı gibi ayrı bir bileşen oluşturun: pagebase.js
Adım 2: Bunun içinde kodu kullanın

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

Adım 3: Herhangi bir bileşende kullanın, onu kullanmak için önce bu bileşeni içe aktarın sonra kullanın. İçeri aktarın ve kullanın:

        import * as base from "./pagebase";

        base.BASE_URL
        base.API_KEY

2

Kullanıyorum babel-plugin-transform-inline-environment-variables.

Yaptığım şey, farklı ortamlarımla S3 içine bir yapılandırma dosyası koymaktı.

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

HER env dosyası:

FIRSTENV=FIRSTVALUE
SECONDENV=SECONDVALUE

Daha sonra, package.jsonpaketlemeye yönelik bir komut dosyası çalıştıran yeni bir komut dosyası ekledim.

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

Uygulamanızda muhtemelen aşağıdakilere sahip bir yapılandırma dosyanız olacaktır:

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

babel ile değiştirilecek olan:

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

UNUTMAYIN, process.env['STRING']KULLANMAMALISINIZ, process.env.STRINGaksi takdirde doğru bir şekilde dönüştürülmez.


REMEMBER you have to use process.env['STRING'] NOT process.env.STRING or it won't convert properly.Teşekkürler! Beni tedirgin eden bu !!!
Steven Yap


1

[Kaynak] Bulduğuma göre, varsayılan olarak görünüyor, yalnızca üretim ve geliştirme yapılandırmaları yapmak mümkün (aşama veya diğer ortamlar yok) - bu doğru mu?

Şu anda, expo yayın kanallarını tespit etmek ve buna dayalı olarak döndürülen değişkenleri değiştirmek için kullanılabilen bir environment.js dosyası kullanıyorum, ancak inşa etmek için, geri dönen DEV değişkeni aşamalandırma veya prod:

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;

Alternatifler

expo ile oluşturulan projeler için react-native-dotenv kullanma deneyimi olan var mı? Düşüncelerini duymak isterim

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


İstediğiniz kadar yayın kanalı adı tanımlayabilir ve ortam değişkeninizi tanımlamak için adı test edebilirsiniz. Sınırlamayı gördüğüm yer, releaseChannel'in tanımsız olduğu geliştirme ortamında. Yani belki babel-plugin-transform-inline-ortam-değişkenlerini kullanabilirsiniz - betiklerinize ortam değişkenlerini aktarabilir ve dev ise, environment.js dosyanızda process.env ['VAR_NAME'] 'e başvurabilirsiniz.
colemerrick

0

ayrıca farklı env komut dosyalarına sahip olabilirsiniz: production.env.sh development.env.sh production.env.sh

Ve sonra çalışmaya başlarken [bu sadece bir takma ada bağlıdır], böylece sh dosyasının sahip olduğu her şey her env değişkeni için dışa aktarılır:

export SOME_VAR=1234
export SOME_OTHER=abc

Ve sonra babel-plugin-transform-inline-ortam değişkenlerinin eklenmesi, bunlara kodda erişime izin verecektir:

export const SOME_VAR: ?string = process.env.SOME_VAR;
export const SOME_OTHER: ?string = process.env.SOME_OTHER;

@ Chapinkapa'nın söylemediği bir şey ekliyor musunuz?
Maximo Dominguez

0

@ chapinkapa'nın cevabı güzel. Mobile Center ortam değişkenlerini desteklemediğinden beri benimsediğim bir yaklaşım, derleme yapılandırmasını yerel bir modül aracılığıyla ortaya çıkarmaktır:

Android'de:

   @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;
    } 

veya ios'ta:

  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]
  }

Derleme yapılandırmasını eşzamanlı olarak okuyabilir ve Javascript'te nasıl davranacağınıza karar verebilirsiniz.


0

Değişkenleri erişmek mümkündür process.env.blablayerine process.env['blabla']. Geçenlerde işe yaradım ve GitHub'daki bir sorunu nasıl yaptığımı yorumladım çünkü kabul edilen cevaba göre önbellekte bazı problemlerim vardı. İşte sorun.


0

Expo kullanıyorsanız, bunu https://docs.expo.io/guides/environment-variables/ belgelerine göre yapmanın 2 yolu vardır.

Yöntem # 1 -.extra Uygulama bildiriminde (app.json) pervane :

Senin içinde app.jsondosyanın

{
  expo: {
    "slug": "my-app",
    "name": "My App",
    "version": "0.10.0",
    "extra": {
      "myVariable": "foo"
    }
  }
}

Ardından, kodunuzdaki (ör. App.js) verilere erişmek için şunları içe aktarmanız yeterlidir expo-constants:

import Constants from 'expo-constants';

export const Sample = (props) => (
  <View>
    <Text>{Constants.manifest.extra.myVariable}</Text>
  </View>
);

Bu seçenek, başka bir paketin kurulmasını gerektirmeyen iyi bir yerleşik seçenektir.

Yöntem 2 - Değişkenleri "değiştirmek" için Babel kullanma. Bu, özellikle çıplak bir iş akışı kullanıyorsanız, muhtemelen ihtiyaç duyacağınız yöntemdir. Diğer cevaplar babel-plugin-transform-inline-environment-variables, bunun nasıl uygulanacağından zaten bahsetti , ancak burada, nasıl uygulanacağına dair resmi belgelere bir bağlantı bırakacağım: https://docs.expo.io/guides/environment-variables/#using-babel-to değişkenleri değiştir

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.