react-create-app 的Issue #578有一个很好的答案。tibdex建议使用使用public/env.js
正确属性生成的 a ,然后index.html
添加:
<script src="%PUBLIC_URL%/env.js"></script>
该env.js
脚本可以在窗口上设置 API_ROOT:
window.env={'API_ROOT':'https://conduit.productionready.io/api'}
并且agent.js
可以检查window.env.API_ROOT
else 默认值:
function apiRoot() {
if( window.env.API_ROOT !== 'undefined') {
return window.env.API_ROOT
}
else {
return 'https://conduit.productionready.io/api'
}
}
const API_ROOT = apiRoot();
该文件是如何从他没有描述的环境变量中创建的,但我能够让npm start
命令生成它。
Moorman然后建议简单地编写一个服务于/env.js
else的快速服务器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);
为了让它工作,启动脚本package.json
很简单:
"start": "PORT=8080 node server.js",
然后一切正常。如果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 以在启动时执行生成 SPA 的 webapp 工作。我们将这种方法作为一种战术解决方法。我们正在使用对内存收费的 saas openshift kubernetes。使用 webpack 构建我们的 react 应用程序需要 1.2Gb(并且还在增加!)因此,这种将 npm 构建移动到容器启动命令的方法我们需要为我们启动的每个 pod 分配 1.2Gb,这对于单个页面来说是大量的额外成本应用程序,而我们可以在应用程序预编译时分配 128MB 作为内存分配。webpack 步骤也很慢,因为它是一个大型应用程序。每次我们启动应用程序时构建都会使滚动部署减慢几分钟。如果 VM 崩溃并且 kubernetes 在新 VM 上启动替换容器,则需要几分钟才能启动。预编译的应用程序会在几秒钟内启动。所以“webpack at startup”的解决方案对于几万行代码的真实业务应用来说,在资源消耗和速度上都不尽如人意。恕我直言,这个从服务器获取配置脚本的答案是优越的。