J'utilise react-native pour créer une application multiplate-forme, mais je ne sais pas comment définir la variable d'environnement pour pouvoir avoir différentes constantes dans 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 d’environnement (je vais vous expliquer comment le faire dans un instant), je suggère d’utiliser le facteur douze suggestion de faire définir votre BASE_URL
et votre API_KEY
.
Pour savoir comment exposer votre environnement à react-native
, je suggère d'utiliser les variables babel-plugin-transform-inline-environment-of de Babel .
Pour que cela fonctionne, vous devez télécharger le plugin, puis vous devez configurer un .babelrc
qui devrait ressembler à ceci:
{
"presets": ["react-native"],
"plugins": [
"transform-inline-environment-variables"
]
}
Et donc, si vous transpilez votre code natif de réaction en exécutant API_KEY=my-app-id react-native bundle
(ou démarrez, run-ios ou run-Android), il vous suffit de faire ressembler votre code à ceci:
const apiKey = process.env['API_KEY'];
Et puis Babel remplacera cela par:
const apiKey = 'my-app-id';
J'espère que cela t'aides!
La solution la plus simple (et non la solution best ou ideal) que j'ai trouvée consistait à utiliser react-native-dotenv . Vous ajoutez simplement le préréglage "react-native-dotenv" à votre fichier .babelrc
à la racine du projet, comme suit:
{
"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"
À mon avis, la meilleure option consiste à utiliser react-native-config . Il prend en charge 12 facteur .
J'ai trouvé ce paquet extrêmement utile. Vous pouvez définir plusieurs environnements, par exemple développement, mise en scène, 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 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
React native n'a pas le concept de variables globales . Il applique la portée modulaire strictement, afin de promouvoir la modularité et la réutilisabilité des composants.
Parfois, cependant, vous avez besoin de composants pour être conscients de leur environnement. Dans ce cas, il est très simple de définir un module Environment
que les composants peuvent ensuite appeler pour obtenir les 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 (e.g. staging, production, etc)
var platform = getPlatform()
// ...now return the correct environment
return _Environments[platform]
}
var Environment = getEnvironment()
module.exports = Environment
my-composant.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 le cadre de votre application. Vous devez explicitement require(...)
le module à partir de tout composant utilisant des variables d'environnement, mais c'est une bonne chose.
J'ai utilisé le polyfill __DEV__
intégré à react-native afin de résoudre ce problème. Il est automatiquement défini sur true
tant que vous ne créez pas, réagissez nativement pour la production.
Par exemple.:
//vars.js
let url, publicKey;
if (__DEV__) {
url = ...
publicKey = ...
} else {
url = ...
publicKey = ...
}
export {url, publicKey}
Alors juste 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 facile et n'implique pas l'ajout de dépendances supplémentaires à votre projet.
La méthode spécifique utilisée pour définir les variables d'environnement varie en fonction du service CI, de l'approche de génération, de la plate-forme et des outils que vous utilisez.
Si vous utilisez Buddybuild for CI pour créer une application et gérer les variables d'environnement , et vous devez accéder à la configuration à partir de JS, créez un env.js.example
avec des clés (avec des valeurs de chaîne vide) pour l'archivage dans le contrôle de code source, et utilisez Buddybuild pour générer un fichier env.js
au moment de la construction à l'étape post-clone
, en masquant le contenu du fichier à partir des journaux de construction, comme suit:
#!/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
Astuce: N'oubliez pas d'ajouter env.js
à .gitignore
afin que les paramètres de configuration et les secrets ne soient pas archivés accidentellement dans le contrôle de source pendant le développement.
Vous pouvez ensuite gérer la manière dont le fichier est écrit en utilisant les variables Buddybuild like 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 morceau manquant du puzzle, 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 ça, c'est que c'est du code asynchrone. Il existe une demande d'extraction pour prendre en charge getSync. Check it out aussi.
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 j'ai commenté comment je l'avais fait sur un problème sur GitHub parce que j'avais quelques problèmes avec le cache en raison de la réponse acceptée. Ici est le problème.
j'ai créé un script de construction préalable pour le même problème car j'ai besoin de points de terminaison api différents 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().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')
})
Et j'ai créé un npm run scripts
personnalisé pour exécuter exécuter natif ..
Mon paquet-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)
[Source] D'après ce que j'ai trouvé, il semble que par défaut, il est uniquement possible de faire des configs de production et de développement (pas de transfert ou d'autres environnements) - est-ce vrai?
À l’heure actuelle, j’utilise un fichier environment.js qui peut être utilisé pour détecter les canaux de publication d’expo et modifier les variables renvoyées en fonction de cela, mais pour la construction, je dois mettre à jour le non DEV variable retournée soit en staging, soit en 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;
Des alternatives
quelqu'un a-t-il déjà utilisé react-native-dotenv pour des projets construits avec expo? J'aimerais entendre vos pensées
Pour les dernières versions de RN, vous pouvez utiliser ce module natif: https://github.com/luggit/react-native-config
J'utilise babel-plugin-transform-inline-environment-variables.
Ce que j'ai fait a été de mettre des fichiers 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
Ensuite, j'ai ajouté un nouveau script dans mon package.json, qui exécute un script pour regrouper
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 convertira pas correctement.
Étape 1: Créez un composant séparé comme celui-ci Nom du composant: pagebase.js
Étape 2: Dans cette utilisation, code ce
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, commencez par importer ce composant, puis utilisez-le . Importez-le et utilisez-le:
import * as base from "./pagebase";
base.BASE_URL
base.API_KEY
vous pouvez également avoir différents scripts env: production.env.sh development.env.sh production.env.sh
Et puis les source dans quand commencer à travailler [qui est juste lié à un alias].
export SOME_VAR=1234
export SOME_OTHER=abc
Et ensuite, ajouter des variables de babel-plugin-transform-inline-environment permettra d'accéder à ces variables dans le code:
export const SOME_VAR: ?string = process.env.SOME_VAR;
export const SOME_OTHER: ?string = process.env.SOME_OTHER;
La réponse de @ Chapinkapa est bonne. Une approche que j'ai adoptée depuis que Mobile Center ne prend pas en charge les variables d'environnement, consiste à exposer la configuration de construction via un module natif:
Sur 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;
}
ou sur 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]
}
Vous pouvez lire la configuration de construction de manière synchrone et décider en Javascript de votre comportement.