Définition de la variable d’environnement dans rea-native?

J’utilise react-native pour créer une application multi-plateforme, mais je ne sais pas comment définir la variable d’environnement pour avoir différentes constantes pour différents environnements.

Exemple:

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

Au lieu de coder en dur les constantes de votre application et de changer l’environnement (je vais vous expliquer comment faire en un instant), je suggère d’utiliser la suggestion des douze facteurs pour que votre processus de construction définisse votre BASE_URL et votre API_KEY .

Pour répondre à la manière d’exposer votre environnement à la react-native , je vous suggère d’utiliser les variables Babel -plugin-transform-inline-environment de Babel.

Pour que cela fonctionne, vous devez télécharger le plug-in, puis vous devrez configurer un .babelrc et cela devrait ressembler à ceci:

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

Et donc, si vous transpirez votre code API_KEY=my-app-id react-native bundle exécutant API_KEY=my-app-id react-native bundle (ou start, run-ios ou run-android), il vous suffit de faire en sorte que votre code ressemble à ceci:

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

Et puis Babel va remplacer cela par:

 const apiKey = 'my-app-id'; 

J’espère que cela t’aides!

La solution la plus simple (pas la meilleure ou la meilleure ) que j’ai trouvée consistait à utiliser rea-native-dotenv . Vous ajoutez simplement le préréglage “react-native-dotenv” à votre fichier .babelrc à la racine du projet comme .babelrc :

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

Créez un fichier .env et ajoutez des propriétés:

 echo "SOMETHING=anything" > .env 

Puis dans votre projet (JS):

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

React native n’a pas le concept de variables globales. Il applique ssortingctement la scope modulaire afin de promouvoir la modularité et la réutilisation des composants.

Parfois, cependant, vous avez besoin de composants pour connaître leur environnement. Dans ce cas, il est très simple de définir un module Environment que les composants peuvent appeler pour obtenir des variables d’environnement, par exemple:

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 (eg 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 

Cela crée un environnement singleton auquel vous pouvez accéder de n’importe où dans la scope de votre application. Vous devez explicitement require(...) le module de tous les composants qui utilisent des variables d’environnement, mais c’est une bonne chose.

A mon avis, la meilleure option est d’utiliser react-native-config . Il prend en charge 12 facteurs .

J’ai trouvé ce paquet extrêmement utile. Vous pouvez définir plusieurs environnements, par exemple le développement, le transfert, la production.

Dans le cas d’Android, les variables sont également disponibles dans les classes Java, gradle, AndroidManifest.xml, etc. Dans le cas d’iOS, les variables sont également disponibles dans les classes Obj-C, Info.plist.

Vous venez de créer des fichiers comme

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

Vous remplissez ces fichiers avec des clés, des valeurs telles que

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

et puis juste l’utiliser:

 import Config from 'react-native-config' Config.API_URL // 'https://myapi.com' Config.GOOGLE_MAPS_API_KEY // 'abcdefgh' 

Si vous souhaitez utiliser différents environnements, vous définissez essentiellement la variable ENVFILE comme suit:

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

ou pour assembler une application pour la production (Android dans mon cas):

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

J’ai utilisé le polyfill __DEV__ -native pour résoudre ce problème. Il est automatiquement défini sur true tant que vous ne construisez pas de réaction native pour la production.

Par exemple:

 //vars.js let url, publicKey; if (__DEV__) { url = ... publicKey = ... } else { url = ... publicKey = ... } export {url, publicKey} 

import {url} from '../vars' simplement import {url} from '../vars' et vous obtiendrez toujours le bon. Malheureusement, cela ne fonctionnera pas si vous voulez plus de deux environnements, mais c’est simple et ne nécessite pas d’append plus de dépendances à votre projet.

La méthode spécifique utilisée pour définir les variables d’environnement variera en fonction du service CI, de l’approche de création, de la plateforme et des outils que vous utilisez.

Si vous utilisez Buddybuild pour CI pour créer une application et gérer les variables d’environnement , et que vous avez besoin d’accéder à la configuration depuis JS, créez un env.js.example avec des clés (avec des valeurs de chaîne vides) pour le contrôle source. utilisez Buddybuild pour produire un fichier env.js au moment de la construction dans l’étape post-clone , en masquant le contenu du fichier à partir des journaux de génération, comme ceci:

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

Astuce: N'oubliez pas d'append env.js à .gitignore afin que la configuration et les secrets ne soient pas .gitignore accidentellement lors du développement.

Vous pouvez ensuite gérer la façon dont le fichier est écrit à l'aide des variables BUDDYBUILD_VARIANTS , BUDDYBUILD_VARIANTS que BUDDYBUILD_VARIANTS , par exemple, pour mieux contrôler la manière dont votre configuration est produite au moment de la construction.

Je pense que quelque chose comme la bibliothèque suivante pourrait vous aider à résoudre le problème, à savoir la fonction 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); }); 

Le seul problème que je vois avec cela, c’est que c’est un code asynchrone. Il y a une demande d’extraction pour prendre en charge getSync. Check it out aussi.

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

J’utilise babel-plugin-transform-inline-environment-variables.

Ce que j’ai fait a été de mettre un fichier de configuration dans S3 avec mes différents environnements.

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

CHAQUE fichier env:

 FIRSTENV=FIRSTVALUE SECONDENV=SECONDVALUE 

Par la suite, j’ai ajouté un nouveau script dans mon package.json qui exécute un script pour grouper

 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 

Dans votre application, vous aurez probablement un fichier de configuration qui a:

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

qui sera remplacé par babel à:

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

RAPPELEZ-VOUS que vous devez utiliser process.env [‘STRING’] PAS process.env.STRING ou il ne sera pas converti correctement.

J’ai créé un script de pré-construction pour le même problème, car j’ai besoin de différents points de terminaison pour les différents environnements

 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().toSsortingng(36).slice(2) } ` fs.writeFile('./src/constants/config.js', template, function (err) { if (err) { return console.log(err) } console.log('Configuration file has generated') }) 

Et j’ai créé des npm run scripts d’exécution npm run scripts personnalisés pour exécuter un npm run scripts .

Mon forfait-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", ... } 

Ensuite, dans mes composants de services, importez simplement le fichier généré automatiquement:

 import config from '../constants/config' fetch(`${config.API_URL}/login`, params) 

Il est possible d’accéder aux variables avec process.env.blabla au lieu de process.env['blabla'] . Je l’ai récemment fait fonctionner et commenté comment je l’ai fait sur un problème sur GitHub car j’avais des problèmes de cache basés sur la réponse acceptée. Voici le problème.

Vous pouvez également avoir différents scripts env: production.env.sh development.env.sh production.env.sh

Et puis les source lorsque vous commencez à travailler [ce qui est juste lié à un alias], donc tout le fichier sh est exporté pour chaque variable env:

 export SOME_VAR=1234 export SOME_OTHER=abc 

Et puis, l’ajout de babel-plugin-transform-inline-environment-variables leur permettra d’accéder au code:

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

La réponse de @ chapinkapa est bonne. Une approche que j’ai prise depuis que Mobile Center ne prend pas en charge les variables d’environnement, consiste à exposer la configuration de la construction via un module natif:

Sur Android:

  @Override public Map getConstants() { final Map constants = new HashMap<>(); String buildConfig = BuildConfig.BUILD_TYPE.toLowerCase(); constants.put("ENVIRONMENT", buildConfig); return constants; } 

ou sur ios:

  override func constantsToExport() -> [Ssortingng: 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: Ssortingng = Bundle.main.bundleIdentifier { if (bundleIdentifier.lowercased().hasSuffix(STAGING)) { environment = STAGING } else if (bundleIdentifier.lowercased().hasSuffix(DEBUG)){ environment = DEBUG } } return ["ENVIRONMENT": environment] } 

Vous pouvez lire la configuration de manière synchrone et décider dans Javascript comment vous allez vous comporter.

Étape 1: Créez un composant distinct comme ce nom de composant: pagebase.js
Étape 2: Dans ce code d’utilisation, cette

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

Étape 3: Utilisez-le dans n’importe quel composant, pour l’utiliser, importez d’abord ce composant, puis utilisez-le. Importez-le et utilisez-le:

  import * as base from "./pagebase"; base.BASE_URL base.API_KEY