react native - node - Configuración de la variable de entorno en react-native?
instalar react native en windows (15)
Estoy usando react-native para construir una aplicación multiplataforma, pero no sé cómo configurar la variable de entorno para poder tener diferentes constantes para diferentes entornos.
Ejemplo:
development:
BASE_URL: '''',
API_KEY: '''',
staging:
BASE_URL: '''',
API_KEY: '''',
production:
BASE_URL: '''',
API_KEY: '''',
Creo que algo como la siguiente biblioteca podría ayudarlo a resolver la parte faltante del rompecabezas, la función 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);
});
El único problema que veo con esto es que es un código asíncrono. Hay una solicitud de extracción para admitir getSync. Compruébalo también.
El método específico utilizado para establecer variables de entorno variará según el servicio de CI, el enfoque de compilación, la plataforma y las herramientas que esté utilizando.
Si está utilizando Buddybuild para CI para construir una aplicación y
administrar variables de entorno
, y necesita acceso a la configuración desde JS, cree un
env.js.example
claves (con valores de cadena vacíos) para el registro en el control de origen, y use Buddybuild para producir un archivo
env.js
en el momento de la compilación en el paso
post-clone
, ocultando el contenido del archivo de los registros de compilación, así:
#!/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
Consejo:
No olvide agregar
env.js
a
.gitignore
para que la configuración y los secretos no se verifiquen accidentalmente en el control de origen durante el desarrollo.
Luego puede administrar cómo se escribe el archivo usando las
variables Buddybuild
como
BUDDYBUILD_VARIANTS
, por ejemplo, para obtener un mayor control sobre cómo se produce su configuración en el momento de la compilación.
En lugar de codificar constantemente las constantes de su aplicación y hacer un cambio en el entorno (explicaré cómo hacerlo en un momento), sugiero usar la sugerencia de
doce factores
para que su proceso de compilación defina su
BASE_URL
y su
API_KEY
.
Para responder cómo exponer su entorno a
react-native
, sugiero usar las
babel-plugin-transform-inline-environment-variables
Babel.
Para que esto funcione, debe descargar el complemento y luego deberá configurar un
.babelrc
y debería verse así:
{
"presets": ["react-native"],
"plugins": [
"transform-inline-environment-variables"
]
}
Entonces, si transpila su código react-native ejecutando
API_KEY=my-app-id react-native bundle
(o start, run-ios o run-android), todo lo que tiene que hacer es hacer que su código se vea así:
const apiKey = process.env[''API_KEY''];
Y luego Babel lo reemplazará con:
const apiKey = ''my-app-id'';
¡Espero que esto ayude!
En mi opinión, la mejor opción es usar react-native-config . Es compatible con 12 factores .
Encontré este paquete extremadamente útil. Puede configurar múltiples entornos, por ejemplo, desarrollo, puesta en escena, producción.
En el caso de Android, las variables están disponibles también en las clases Java, gradle, AndroidManifest.xml, etc. En el caso de iOS, las variables también están disponibles en las clases Obj-C, Info.plist.
Simplemente creas archivos como
-
.env.development
-
.env.staging
-
.env.production
Rellena estos archivos con clave, valores como
API_URL=https://myapi.com
GOOGLE_MAPS_API_KEY=abcdefgh
y luego solo utilízalo:
import Config from ''react-native-config''
Config.API_URL // ''https://myapi.com''
Config.GOOGLE_MAPS_API_KEY // ''abcdefgh''
Si desea utilizar diferentes entornos, básicamente configura la variable ENVFILE de esta manera:
ENVFILE=.env.staging react-native run-android
o para ensamblar aplicaciones para producción (Android en mi caso):
cd android && ENVFILE=.env.production ./gradlew assembleRelease
Es posible acceder a las variables con
process.env.blabla
lugar de
process.env[''blabla'']
.
Recientemente lo hice funcionar y comenté cómo lo hice en un problema en GitHub porque tuve algunos problemas con el caché en función de la respuesta aceptada.
Here
está el problema.
He creado un script de compilación previa para el mismo problema porque necesito algunos puntos finales de API diferentes para los diferentes entornos.
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'')
})
Y he creado
npm run scripts
personalizados para ejecutar la ejecución de
reacción nativa.
Mi paquete-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",
...
}
Luego, en mis componentes de servicios, simplemente importe el archivo generado automáticamente:
import config from ''../constants/config''
fetch(`${config.API_URL}/login`, params)
La respuesta de @ chapinkapa es buena. Un enfoque que he tomado desde que Mobile Center no admite variables de entorno es exponer la configuración de compilación a través de un módulo nativo:
En 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;
}
o en 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]
}
Puede leer la configuración de compilación sincrónicamente y decidir en Javascript cómo se comportará.
La solución más simple (no la
mejor
o la
ideal
) que encontré fue usar
react-native-dotenv
.
Simplemente agregue el preset "react-native-dotenv" a su archivo
.babelrc
en la raíz del proyecto de la siguiente manera:
{
"presets": ["react-native", "react-native-dotenv"]
}
Cree un archivo
.env
y agregue propiedades:
echo "SOMETHING=anything" > .env
Luego en su proyecto (JS):
import { SOMETHING } from ''react-native-dotenv''
console.log(SOMETHING) // "anything"
Para las últimas versiones de RN, puede usar este módulo nativo: react-native-config
Paso 1: Cree un componente separado como este Nombre del componente:
pagebase.js
Paso 2: dentro de este código de uso esto
export const BASE_URL = "http://192.168.10.10:4848/";
export const API_KEY = ''key_token'';
Paso 3: Úselo en cualquier componente, para usarlo primero importe este componente y luego úselo. Importarlo y usarlo:
import * as base from "./pagebase";
base.BASE_URL
base.API_KEY
React native no tiene el concepto de variables globales. Aplica estrictamente el alcance modular , para promover la modularidad y la reutilización de los componentes.
A veces, sin embargo, necesita componentes para conocer su entorno.
En este caso, es muy simple definir un módulo de
Environment
que los componentes pueden llamar para obtener variables de entorno, por ejemplo:
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
Esto crea un entorno
singleton
que se puede acceder desde cualquier lugar dentro del alcance de su aplicación.
Debe
require(...)
explícitamente
require(...)
el módulo de cualquier componente que use variables de entorno, pero eso es algo bueno.
Utilicé el polyfill
__DEV__
que está integrado en react-native para resolver este problema.
Se establece automáticamente en
true
siempre que no esté creando reacción nativa para la producción.
P.ej:
//vars.js
let url, publicKey;
if (__DEV__) {
url = ...
publicKey = ...
} else {
url = ...
publicKey = ...
}
export {url, publicKey}
Luego solo
import {url} from ''../vars''
y siempre obtendrás el correcto.
Desafortunadamente, esto no funcionará si desea más de dos entornos, pero es fácil y no implica agregar más dependencias a su proyecto.
Yo uso
babel-plugin-transform-inline-environment-variables
.
Lo que hice fue poner un archivo de configuración dentro de S3 con mis diferentes entornos.
s3://example-bucket/dev-env.sh
s3://example-bucket/prod-env.sh
s3://example-bucket/stage-env.sh
CADA archivo env:
FIRSTENV=FIRSTVALUE
SECONDENV=SECONDVALUE
Luego, agregué un nuevo script en mi
package.json
que ejecuta un script para agrupar
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
Dentro de su aplicación, probablemente tendrá un archivo de configuración que tiene:
const FIRSTENV = process.env[''FIRSTENV'']
const SECONDENV = process.env[''SECONDENV'']
que será reemplazado por babel para:
const FIRSTENV = ''FIRSTVALUE''
const SECONDENV = ''SECONDVALUE''
RECUERDE que debe usar
process.env[''STRING'']
NO
process.env.STRING
o no se convertirá correctamente.
también puede tener diferentes scripts env: production.env.sh development.env.sh production.env.sh
Y luego instálelos cuando comience a funcionar [que está vinculado a un alias] para que todo el archivo sh se exporte para cada variable env:
export SOME_VAR=1234
export SOME_OTHER=abc
Y luego agregar babel-plugin-transform-inline-environment-variables permitirá acceder a ellas en el código:
export const SOME_VAR: ?string = process.env.SOME_VAR;
export const SOME_OTHER: ?string = process.env.SOME_OTHER;
[Source] Por lo que he encontrado, parece que, de forma predeterminada, solo es posible realizar configuraciones de producción y desarrollo (sin escenarios u otros entornos), ¿es así?
En este momento, he estado usando un archivo environment.js que se puede usar para detectar canales de lanzamiento de expo y cambiar las variables devueltas en función de eso, pero para compilar, necesito actualizar la variable que no es DEV devuelta para ser puesta en escena o pinchar:
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;
Alternativas
¿Alguien tiene experiencia con react-native-dotenv para proyectos creados con expo? Me encantaría escuchar tus pensamientos