sim*_*905 4 12factor reactjs react-redux
https://github.com/gothinkster/react-redux-realworld-example-app上的react redux realworld.io应用程序的自述文件说要编辑以src/agent.js
将其更改API_ROOT
为指向不同的后端api实例.我们想要进行设置,以便API_ROOT
可以通过在我们运行生产构建的多个环境(例如,"staging"和"live")中不同的环境变量来定义.
我们按照12factor.net原则在openshift kubernetes上运行容器,其中代码构建一次,然后通过环境进行推广.我们可以使用单个命令启动新环境,因此我们不希望在代码中有一个switch语句来命名每个环境,并且硬编码每个环境的后端API_ROOT
.相反,我希望能够使用环境变量在新环境中运行现有生产构建容器映像,将其更改API_ROOT
为指向我们要测试的正确后端API.
我查看了许多不同的博客,stackoverflow答案和官方文档.主要问题是典型的解决方案process.env.API_ROOT
在构建时"烘焙" 环境变量,否则就会有一个开关,将所有环境的细节硬编码到代码中.这两者都不令人满意,因为我们希望能够在现有容器中获取最新的稳定代码,并使用在那里运行的API在新环境中运行它.
到目前为止,我最接近的是编辑代码以将其呈现process.env.API_ROOT
为将<script>
其设置在window.API_ROOT
变量上的标记.然后检查是否存在其他在为API_ROOT定义const时使用默认值.这感觉非常具有侵略性,有点脆弱,我不清楚在示例应用程序中在哪里提供这样的脚本标记的最佳位置https://github.com/gothinkster/react-redux-realworld-example-app
sim*_*905 11
react-create-app的问题#578有一个很好的答案.tibdex建议使用使用public/env.js
正确属性生成的,然后在index.html
add中:
<script src="%PUBLIC_URL%/env.js"></script>
Run Code Online (Sandbox Code Playgroud)
该env.js
脚本可以在窗口上设置API_ROOT:
window.env={'API_ROOT':'https://conduit.productionready.io/api'}
Run Code Online (Sandbox Code Playgroud)
并且agent.js
可以检查window.env.API_ROOT
其他默认值:
function apiRoot() {
if( window.env.API_ROOT !== 'undefined') {
return window.env.API_ROOT
}
else {
return 'https://conduit.productionready.io/api'
}
}
const API_ROOT = apiRoot();
Run Code Online (Sandbox Code Playgroud)
究竟如何从他没有描述的环境变量创建该文件,但我能够让npm start
命令生成它.
然后Moorman建议简单地编写一个服务于/env.js
其他服务器的快速服务器index.html
:
const express = require('express');
const path = require('path');
const app = express();
app.use(express.static(path.join(__dirname, 'build')));
const WINDOW_ENV = "window.env={'API_ROOT':'"+process.env.API_ROOT+"'}\n";
app.get('/env.js', function (req, res) {
res.set('Content-Type', 'application/javascript');
res.send(WINDOW_ENV);
});
app.get('/*', function (req, res) {
res.sendFile(path.join(__dirname, 'build', 'index.html'));
});
app.listen(process.env.PORT);
Run Code Online (Sandbox Code Playgroud)
要使其工作,启动脚本package.json
就是:
"start": "PORT=8080 node server.js",
Run Code Online (Sandbox Code Playgroud)
一切正常.如果API_ROOT
在环境变量定义,则server.js
将会产生它window.env
和agent.js
将使用它.
更新我在env.js上设置了五分钟的缓存时间, res.setHeader("Cache-Control", "public, max-age=300");
因为设置很少会改变.
更新我读了很多关于这个主题的混淆,人们在回答"改变你的工作流程以适应工具的默认值"这句话.12因素的想法是使用工作流程,该工作流程被建立为工具应遵循的最佳实践,反之亦然.具体而言,标记的生产就绪容器应该可以通过环境变量进行配置并通过环境进行升级.然后,调试和测试的"同样的东西"在现场运行.在单页应用程序的这种情况下,它要求浏览器访问服务器以加载环境变量,而不是将它们烘焙到应用程序中.恕我直言这个答案是一种简单明了的方法,可以遵循12因素最佳实践.
更新:@mikesparr在https://github.com/facebook/create-react-app/issues/982#issuecomment-393601963给出了一个很好的答案,这 是重组package.json来做webapp的生成工作SPA启动时.我们采用这种方法作为战术解决方法.我们正在使用saas openshift kubernetes为记忆收费.使用webpack构建我们的react应用程序需要1Gb(并且还在上升!)所以这种将npm构建移动到容器启动命令的方法我们需要为每个启动的pod分配1Gb,这对于单个页面应用程序来说是一个相当大的额外成本,而当预编译应用程序时,我们可以使用128MB作为内存分配.webpack步骤也很慢,因为它是一个大型应用程序.每次启动应用程序时构建都会使滚动部署减慢许多分钟.如果VM崩溃并且kubernetes在新VM上启动替换容器,则启动需要几分钟.预编译的应用程序会在几秒钟内启动.因此,"webpack at startup"的解决方案在资源消耗和速度方面远远不能令人满意.恕我直言这个从服务器获取配置脚本的答案是优越的.
您可以直接在 index.html 文件中替换环境变量,从而公开全局 ENV 变量。该替换需要在运行时完成,以确保您拥有可以在不同环境中运行的可移植映像。
我在这里创建了一个示例存储库https://github.com/axelhzf/create-react-app-docker-environment-variables
归档时间: |
|
查看次数: |
3637 次 |
最近记录: |