Answers:
建议不要使用十二个因素建议,让您的构建过程定义您BASE_URL
和您的应用,而不是对应用程序常数进行硬编码并在环境上进行切换(我将在稍后说明)。API_KEY
。
为了回答如何将您的环境暴露在其中react-native
,我建议使用Babel的babel-plugin-transform-inline-environment-variables。
要使其正常工作,您需要下载插件,然后需要设置,.babelrc
并且其外观应如下所示:
{
"presets": ["react-native"],
"plugins": [
"transform-inline-environment-variables"
]
}
因此,如果您通过运行API_KEY=my-app-id react-native bundle
(或启动,run-ios或run-android)来转换本机代码,那么您要做的就是使代码如下所示:
const apiKey = process.env['API_KEY'];
然后Babel将其替换为:
const apiKey = 'my-app-id';
希望这可以帮助!
process.env
是NODE_ENV
。
process.env.API_KEY
... 访问变量,请process.env['API_KEY']
改用
react-native start --reset-cache
每次更改环境变量时运行,以清除捆绑程序的缓存。
我发现最简单的(不是最佳或理想的)解决方案是使用react-native-dotenv。您只需.babelrc
在项目根目录的文件中添加“ react-native-dotenv”预设即可,如下所示:
{
"presets": ["react-native", "react-native-dotenv"]
}
创建一个.env
文件并添加属性:
echo "SOMETHING=anything" > .env
然后在您的项目(JS)中:
import { SOMETHING } from 'react-native-dotenv'
console.log(SOMETHING) // "anything"
base_url
为staging
和配置一个production
?
.env
文件(每个环境),还是要在不同的文件中重用某些值.env
,这样您就不会在登台和生产中重复使用它们?
.env
每个环境的不同文件,例如staging
和production
。
我认为最好的选择是使用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
或组装用于生产的应用程序(在我的情况下为android):
cd android && ENVFILE=.env.production ./gradlew assembleRelease
React native没有全局变量的概念。它严格执行模块化范围,以促进组件的模块化和可重用性。
但是,有时您需要组件来了解其环境。在这种情况下,定义一个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(...)
从使用环境变量的所有组件中显式地定义模块,但这是一件好事。
getPlatform()
。我做这样的文件,但不能在这里完成逻辑阵营原住民
staging
或者production
甚至平均,因为它依赖于您的环境。例如,如果您希望IOS和Android使用不同的风格,则可以通过导入Environment index.ios.js
和index.android.js
文件并在其中设置平台来初始化Environment ,例如Environment.initialize('android')
。
我使用了__DEV__
内置于react-native 的polyfill来解决此问题。true
只要您不构建用于生产的本机反应,它将自动设置为。
例如:
//vars.js
let url, publicKey;
if (__DEV__) {
url = ...
publicKey = ...
} else {
url = ...
publicKey = ...
}
export {url, publicKey}
然后公正import {url} from '../vars'
,您将永远得到正确的。不幸的是,如果您需要两个以上的环境,那么这将行不通,但是它很简单,并且不需要在项目中添加更多的依赖项。
用于设置环境变量的特定方法会因CI服务,构建方法,所使用的平台和工具而异。
如果您使用Buddybuild for CI来构建应用程序和管理环境变量,并且需要从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扩展名,所以我对这部分的含义有些困惑
env.js.example
文件作为参考文档位于代码库中,是有关应用程序要使用的配置键的一个真实的标准来源。两者都描述了运行该应用程序所需的键以及复制和重命名后预期的文件名。该模式在使用dotenv gem的 Ruby应用程序中很常见,这就是我从中提出该模式的地方。
我认为类似以下库的内容可以帮助您解决难题的缺失部分,即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。也检查一下。
我已经针对同一问题创建了预构建脚本,因为我需要针对不同环境的一些不同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
来执行 react-native运行..
我的package-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)
步骤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
我用 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
每个环境文件:
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.
谢谢!这是让我绊倒的那个!!!
[来源]根据我的发现,默认情况下看起来像是只能进行生产和开发配置(没有暂存或其他环境)–是吗?
现在,我一直在使用一个environment.js文件,该文件可用于检测expo发布通道并基于此更改返回的变量,但是对于构建,我需要将返回的non- DEV变量更新为staging或产品:
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;
备择方案
有没有人对使用expo构建的项目使用react-native-dotenv有经验?我很想听听你的想法
您还可以具有不同的环境脚本: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的答案很好。自从Mobile Center不支持环境变量以来,我采取的一种方法是通过本机模块公开构建配置:
在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;
}
或在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中决定您的行为方式。
可以使用process.env.blabla
代替访问变量process.env['blabla']
。我最近使其工作并评论了我在GitHub上的问题上的处理方式,因为基于公认的答案,我在缓存方面遇到了一些问题。这是问题。
对于最新的RN版本,您可以使用以下本机模块:https : //github.com/luggit/react-native-config
import {Platform} from 'react-native';
console.log(Platform);