Spa*_*ear 6 reactjs react-native
我已经建立了一个reactjs网站并试图使其可部署。
现在,所有配置都通过导入到所有模块中的config.js完成。
但是,当我构建应用程序时,它会被编译到部署js中,并且是不可配置的。
我想拥有一个单独的文件,系统管理员可以根据其环境配置各种设置,例如API端点(该应用程序可能与后端未在同一服务器上运行,并且将无法访问DNS )。
有办法做到这一点吗?我也不希望为此使用第三方库。
我已经设法破解了一个解决方案。
在公共文件夹“config.js”中
var config = {
x: 'y',
};
Run Code Online (Sandbox Code Playgroud)
接下来包装 ReactDOM.render(App/index.js 像这样
window.RenderApp = (config) => {
ReactDOM.render(<App _config={config}/>, document.getElementById('root'));
}
Run Code Online (Sandbox Code Playgroud)
在 index.html 中添加这些行,window.RenderApp 必须在最后,因为它依赖于 bundle.js 被导入,它是由 react 自动添加的,并且在生产中具有随机名称。
</html>
...
<head>
...
<script type="text/javascript" src="%PUBLIC_URL%/config.js"></script>
...
</head>
...
<body>
...
</body>
<script>
window.RenderApp(config);
</script>
</html>
Run Code Online (Sandbox Code Playgroud)
最后在你的 App.js 中使用配置变量或者你叫它什么
...
constructor(props) {
super(props)
console.log(this.props._config)
this.state = {
....
config: this.props._config,
}
}
...
Run Code Online (Sandbox Code Playgroud)
我发现您必须将 config 设置为状态变量,否则它会随机为对象抛出 undefined ,现在只需将 config 传递到层次结构中即可在您的代码中使用。
不确定Linux的方法,但是我经常使用create-react-app(cra),Docker和kubernetes,并最初遇到类似问题。然后,我受到https://github.com/inloop/cra-docker的启发,能够在运行时在Docker和kubernetes中使用create-react-app找到解决配置文件问题的解决方案。以下是我的解决方案中的步骤:
config.js准备好您的自定义配置(例如:)。配置文件中的内容应如下所示:
window.ENV = {
"ENVIRONMENT":"stg",
...other key-value configuration as you'll need
}
Run Code Online (Sandbox Code Playgroud)您可以通过访问代码的任何位置来访问您的配置window.ENV.your_configuration_key(例如,可以在上方找到上述ENVIRONMENT值window.ENV.ENVIRONMENT)
在public目录下,编辑index.html并添加
<script type="text/javascript" src="%PUBLIC_URL%/config.js"></script>
Run Code Online (Sandbox Code Playgroud)在身体前的头部。并放在目录config.js下public。
解决cra的外部配置的目标是,您希望将config.js文件放在源目录之外,并将其放在静态public目录下。如果将配置放在源目录下,则配置将在构建时进行编译,因此您将无法在运行时轻松更改配置(当然,模板也可以,但对我而言并不理想)。请注意,从静态目录提供文件需要一台服务器,但是由于我已经在使用nginx静态响应应用程序提供服务了,因此这样做绝对没有问题。
由于我已经nginx在为我的react应用程序提供静态文件,因此我不需要对Dockerfile进行更改以迎合其他需求,config.js因为它build在编译后将在目录下可用(由于将其放置在public目录下)。我的Dockerfile看起来像这样:
# Step 1: Build static react app
FROM node AS builder
# Define working directory and copy source
WORKDIR /app
COPY . .
# Install dependencies and build whatever you have to build
RUN yarn install && yarn build
# Step 2: Run image
FROM nginx
COPY --from=builder /app/build /usr/share/nginx/html
RUN rm /etc/nginx/conf.d/default.conf
COPY nginx.conf /etc/nginx # this step is not required, only when you have custom nginx configuration
Run Code Online (Sandbox Code Playgroud)然后,构建您的docker映像: docker build -t [your-docker-image]:latest .
config.js在运行时替换文件。现在可以很容易地做到这一点。如果使用docker运行,则可以使用-v命令替换文件。因此,您的docker运行时命令应类似于以下内容:
docker run --name [app-container-name] -d -p [host_port]:80 \
-v [path_to_config.js_file_in_certain_environment]:/usr/share/nginx/html/config.js \
[your-docker-image]
Run Code Online (Sandbox Code Playgroud)
如果您使用kubernetes运行,您可以通过使用替代在现有目录中的文件的容器下configMap,volume,volumeMounts和subPath。
首先将您的config.js放在k8s ConfigMap下:
kubectl create configmap [k8s_config_name] --from-file=config.js=[path_to_config.js_file_in_certain_environment]
Run Code Online (Sandbox Code Playgroud)在您的k8s部署中挂载configMap:
containers:
...
volumeMounts:
- name: [k8s_config_name_volume]
readOnly: true
mountPath: "/usr/share/nginx/html/config.js"
subPath: "config.js"
volumes:
- name: [k8s_config_name_volume]
configMap:
name: [k8s_config_name]
Run Code Online (Sandbox Code Playgroud)请注意,必须替换mountPath和subPath参数,以替换目录中已有文件的目录下的文件。如果subPath在将卷装入到已经包含一些文件的现有目录的过程中省略了该结果,那么在我们的情况下,结果是不利的,它将通过将新文件复制到该目录中但删除所有其他先前存在的文件来覆盖现有目录。
小智 6
这是我的解决方案。
考虑拥有一些“您知道配置”的环境和“您不知道配置”的其他环境,但它们必须由系统管理员配置。
例如 3 个环境:您知道配置的本地和 uat,以及您不知道要设置的配置的生产环境。
所以,我不希望为特定环境自动生成配置文件,并且该配置文件必须是可编辑的
我们可以使用 config.js 文件来放置 json 对象。
所以,首先进入index.html并添加head
<script src="config.js"></script>
Run Code Online (Sandbox Code Playgroud)
这意味着 config.js 文件必须位于已编译的根文件夹中(与 index.html 的位置相同),这意味着位于 React 解决方案的“public”文件夹中。但我们希望这个 config.js 是基于环境的动态的。
考虑在反应解决方案根文件夹中创建一个名为“config”的文件夹。在此文件夹中放入3个文件:config_local.js、config_uat.js、config_prod.js
-config_local.js
var Configs = {
API_ENDPOINT':"http://local:88/service"
}
Run Code Online (Sandbox Code Playgroud)
-config_uat.js
var Configs = {
'API_ENDPOINT':"http://uat:88/service"
}
Run Code Online (Sandbox Code Playgroud)
-config_prod.js
var Configs = {
'API_ENDPOINT':""
}
Run Code Online (Sandbox Code Playgroud)
我们需要将这 3 个文件之一复制到根文件夹中,将输出文件重命名为“config.js”
因此,首先我们需要为每个环境都有一个 .env 文件。在此 env 文件中,我们只想设置将复制到根文件夹中的文件名。
因此,在react根文件夹中创建.env、.env.uat、.env.local、.env.prod
-.env(这是默认值)
REACT_APP_CONFIG_FILE=config_prod.js
Run Code Online (Sandbox Code Playgroud)
-.env.local
REACT_APP_CONFIG_FILE=config_local.js
Run Code Online (Sandbox Code Playgroud)
-.env.uat
REACT_APP_CONFIG_FILE=config_uat.js
Run Code Online (Sandbox Code Playgroud)
-.env.prod
REACT_APP_CONFIG_FILE=config_prod.js
Run Code Online (Sandbox Code Playgroud)
我们需要在 package.json 中添加/替换脚本对象。之前我们需要安装 env-cmd (npm install env-cmd)。这是脚本的示例
"scripts": {
"start": "env-cmd -f ./.env react-app-rewired start",
"build": "env-cmd -f ./.env react-app-rewired build",
"test": "env-cmd -f ./.env react-app-rewired test",
"start:local": "env-cmd -f ./.env.local react-app-rewired start",
"build:local": "env-cmd -f ./.env.local react-app-rewired build",
"start:uat": "env-cmd -f ./.env.uat react-app-rewired start",
"build:uat": "env-cmd -f ./.env.uat react-app-rewired build",
"start:prod": "env-cmd -f ./.env.prod react-app-rewired start",
"build:prod": "env-cmd -f ./.env.prod react-app-rewired build"
},
Run Code Online (Sandbox Code Playgroud)
PS:我使用过react-app-rewired。我需要它,因为我们需要使用 CopyFile 插件,但我无法在 webpack 中设置它,因为我的应用程序是使用 create-react-app 创建的。因此,如果您没有 webpack 文件,请使用 npm install react-app-rewired 安装 rewired
现在,我们需要根据具体环境复制具体的js文件。因此,如果我们没有 webpack,则使用 npm install copy-webpack-plugin 安装 copyfile 示例:
在 React 根文件夹中创建一个名为“config-overrides.js”的文件,然后复制以下内容:
const CopyWebpackPlugin = require('copy-webpack-plugin');
let internal_env = process.env.REACT_APP_CONFIG_FILE || 'config_prod.js';
module.exports = function override(config, env) {
if (!config.plugins) {
config.plugins = [];
}
config.plugins.push(
new CopyWebpackPlugin(
[
{
from: 'config/' + internal_env,
to: './config.js'
}
])
);
return config;
};
Run Code Online (Sandbox Code Playgroud)
因此,在我们的反应文件中,我们可以使用以下方式读取配置:
//@ts-ignore
const apiEndpoint = Configs.API_ENDPOINT || ''
Run Code Online (Sandbox Code Playgroud)
注意:如果您使用 typescript,则需要忽略,因为我们无法将配置导入为模块
因此,现在您可以根据所需的环境使用其中之一来启动或构建:
npm run start
npm run build
npm run start:local
npm run build:local
npm run start:uat
npm run build:uat
npm run start:prod
npm run build:prod
Run Code Online (Sandbox Code Playgroud)
当您可以构建时,会在根应用程序文件夹中生成特定的 config.js 并且可以编辑(例如由系统管理员)
我真的很喜欢您使用配置文件的方法,您可以根据需要替换/更新该配置文件。我想当我有时间的时候我可以尝试一下 - 感谢分享你的方法!
我当前处理动态客户端配置的方式基于正在访问的应用程序的 URL - 我使用它能够通过我们的部署管道(开发 -> 测试 -> 登台 -> 生产)移动捆绑包,而无需重建捆绑包。
env.js:
const rootUrl = `${location.protocol}//${location.host}`;
deployment-settings
const envs = {
// Production
'https://example.com': {
APP_ENV: 'production',
API_SERVER: 'https://api.example.io',
INTERCOM_APP_ID: 'foo',
},
// Staging
'https://staging.example.com': {
APP_ENV: 'staging',
API_SERVER: 'https://staging-api.example.com',
INTERCOM_APP_ID: 'bar',
},
// Development
'http://localhost:3000': {
APP_ENV: 'development',
API_SERVER: 'http://localhost:4000',
INTERCOM_APP_ID: 'baz',
},
};
if (envs[rootUrl]) {
// Set environment variables based on the URL the app is being accessed from
window.env = envs[rootUrl];
} else {
// Redirect to production if the rootUrl is unknown
window.location.replace(Object.keys(envs)[0]);
}
Run Code Online (Sandbox Code Playgroud)
小智 5
我们有一个类似的用例 - “构建一次,随处部署”。以下代码似乎对我们有用:
目录中有一个config.js文件,public代码如下:
const API_URL = '<API_URL>';
index.html 文件包含以下内容:
<script src="/config.js"></script>
<script>
(function (global) {
var config = {
API_URL
};
global.app = {
env: config
};
})(window);
Run Code Online (Sandbox Code Playgroud)
这会将变量添加config.js到global作用域中,并且可以在源代码中的任何位置访问,如 : const API_ROOT = window.app && window.app.env.API_URL;。
| 归档时间: |
|
| 查看次数: |
4088 次 |
| 最近记录: |