我正在使用react-native来构建一个跨平台的应用程序,但我不知道如何设置环境变量,以便我可以有不同的常量为不同的环境。
例子:
development:
BASE_URL: '',
API_KEY: '',
staging:
BASE_URL: '',
API_KEY: '',
production:
BASE_URL: '',
API_KEY: '',
我正在使用react-native来构建一个跨平台的应用程序,但我不知道如何设置环境变量,以便我可以有不同的常量为不同的环境。
例子:
development:
BASE_URL: '',
API_KEY: '',
staging:
BASE_URL: '',
API_KEY: '',
production:
BASE_URL: '',
API_KEY: '',
当前回答
如果你使用的是Expo,根据文档https://docs.expo.io/guides/environment-variables/有两种方法
方法#1 -在应用程序清单(app.json)中使用.extra道具:
在你的app.json文件中
{
expo: {
"slug": "my-app",
"name": "My App",
"version": "0.10.0",
"extra": {
"myVariable": "foo"
}
}
}
然后要访问你的代码(即App.js)上的数据,只需导入expo-constants:
import Constants from 'expo-constants';
export const Sample = (props) => (
<View>
<Text>{Constants.manifest.extra.myVariable}</Text>
</View>
);
这个选项是一个很好的内置选项,不需要安装任何其他包。
方法#2 -使用Babel“替换”变量。这是您可能需要的方法,特别是当您正在使用裸工作流时。其他的答案已经提到了如何使用babel-plugin-transform-inline-environment-variables来实现它,但是我将在这里留下一个官方文档的链接来说明如何实现它:https://docs.expo.io/guides/environment-variables/#using-babel-to-replace-variables
其他回答
步骤1:像这样创建单独的组件 组件名称:pagebase.js 步骤2:在此使用代码this
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
嗨,如果你正面临这个问题,试试这个,这对我有用,以后谢谢我
在bable.js
plugins: [
[
"module:react-native-dotenv",
{
moduleName: "react-native-dotenv",
},
],
],
use
import { YOURAPIKEY } from "react-native-dotenv";
inseted of
import { YOURAPIKEY } from "@env";
遵循以下步骤
NPM安装react-native-dotenv 用一些变量名设置。env文件,例如APP_NAME="my-app" 修改bable.config.js
模块。出口= { 预设:['模块:metro-react-native-babel-preset '), 插件:[ ["模块:react-native-dotenv ", { :“envName APP_ENV”, :“moduleName @env”, “路径”:“.env”, “安全”:假的, “allowUndefined”:没错, “详细”:假的 }) ] };
重新启动所有应用程序 尝试从“@env”导入{APP_NAME}。如果这不起作用,那么执行这个const APP_NAME = process.env['APP_NAME'];
欢呼:)
@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中决定如何执行。
经过长时间的努力,我意识到react-native并没有正式提供这个功能。这是在babel生态系统中,所以我应该学习如何写一个babel插件…
/**
* A simple replace text plugin in babel, such as `webpack.DefinePlugin`
*
* Docs: https://github.com/jamiebuilds/babel-handbook
*/
function definePlugin({ types: t }) {
const regExclude = /node_modules/;
return {
visitor: {
Identifier(path, state) {
const { node, parent, scope } = path;
const { filename, opts } = state;
const key = node.name;
const value = opts[key];
if (key === 'constructor' || value === undefined) { // don't replace
return;
}
if (t.isMemberExpression(parent)) { // not {"__DEV__":name}
return;
}
if (t.isObjectProperty(parent) && parent.value !== node) { // error
return;
}
if (scope.getBinding(key)) { // should in global
return;
}
if (regExclude.test(filename)) { // exclude node_modules
return;
}
switch (typeof value) {
case 'boolean':
path.replaceWith(t.booleanLiteral(value));
break;
case 'string':
path.replaceWith(t.stringLiteral(value));
break;
default:
console.warn('definePlugin only support string/boolean, so `%s` will not be replaced', key);
break;
}
},
},
};
}
module.exports = definePlugin;
就这样,然后你可以这样用:
module.exports = {
presets: [],
plugins: [
[require('./definePlugin.js'), {
// your environments...
__DEV__: true,
__URL__: 'https://example.org',
}],
],
};
回答者提到的包也很棒,我也参考了metro-transform-plugins/src/inline-plugin.js。