同构 React 中的实时环境变量

Posted

技术标签:

【中文标题】同构 React 中的实时环境变量【英文标题】:Live Environment Vars in Isomorphic React 【发布时间】:2015-12-22 19:04:03 【问题描述】:

我基于this repo 中的入门套件松散地构建了一个同构 React 应用程序。它使用 webpack 构建生产代码。

问题是,我需要将服务器上的一些环境变量的值暴露给浏览器中的客户端代码,而不需要重新构建生产代码。我希望能够更改环境变量的值,并使其在客户端刷新下一页时产生效果,而无需重建任何内容。而且我不想为了做到这一点而使测试复杂化。

我找到了一些解决方案,但都不是很好:

    使用DefinePlugin for webpack 将某些环境变量的值硬编码到生产代码中。类似于here 的概述 构建一个 API 只是为了将环境变量拉入客户端。 在 webpack 系统之外编写一个特殊的 .js 文件。该文件将被模板化,以便在提供给客户端之前对其进行修改。可能需要将环境变量值存储在“窗口”或其他东西上的特殊全局变量中。

这些方法的问题:

    被拒绝。这只是不符合我的要求。如果我更改了 env 变量的值,我需要重新构建代码。 不必要的复杂。我不需要这个 API 来做其他事情。一个完整的 API 只是为了提供 2 或 3 个很少更改的值?需要复杂性来确保在加载时尽快从 API 中提取值。 最接近,但有点恶心。如果可以避免的话,我真的不想离开 webpack/React/Flux 系统。在窗口对象上创建特殊的全局变量是可行的,但会增加测试使用这些全局变量的组件/存储/操作的复杂性。

我过去做过 2 和 3,但从来没有对这些解决方案在智力上真正感到满意。

有什么建议吗?似乎这应该是一个常见/已解决的问题。也许我只是想多了,3是要走的路。

【问题讨论】:

3 似乎是最好的选择。 【参考方案1】:

这使用window 中的窗口全局变量来传递值,但为您提供了一个通用接口来访问浏览器和节点上的值。

publicEnv.js:

// Env variable to push to the client. Careful on what you put here!
const publicEnv = [
  'API_URL',
  'FACEBOOK_APP_ID',
  'GA_ID'
];

// These 2 lines make sure we pick the value in the right place on node and the browser
const isBrowser = typeof window !== 'undefined';
const base = (isBrowser ? window.__ENV__ : process.env) || ;

const env = ;
for (const v of publicEnv) 
  env[v] = base[v];

export default env;

在我拥有的页面的 html 模板文件中:

import publicEnv from 'publicEnv.js';

...

<script>
  window.__ENV__ = $stringify(publicEnv);

  // Other things you need here...
  window.__INITIAL_STATE__ = $stringify(initialState);
</script>

所以现在我可以在前端和后端获取环境变量的值:

import publicEnv from 'publicEnv.js';

...

console.log("Google Analytic code is", publicEnv.GA_ID);

希望对你有帮助。

【讨论】:

【参考方案2】:

所以我想出的解决方案相当简单。我只是编写了一行 javascript 来将值保存到脚本标记内的本地存储中。然后在应用启动时从我的通量存储中读取该本地存储。

这是添加到 index.html 中的相关标签:

<script type="text/javascript"><%= config %></script>

这是我在提供之前使用模板拼接到 index.html 中的字符串:

let configJs = 'localStorage.setItem(\'ADMIN_API\', JSON.stringify(\'' + process.env.ADMIN_API + '/v3/' + '\'));';
const html = template(config: configJs);
res.status(200).send(html);

然后我在应用程序启动后阅读它:

import ls from 'local-storage';
....
let api = ls.get('ADMIN_API');

【讨论】:

【参考方案3】:

样板使用 express,您可以使用 express'local 向客户端公开服务器环境变量。

var serverVariable = 'this is a server variable'
app.get('/somelink', function (req, res, next) 
    res.locals.data = 
      FluxStore:  serverlocal: serverVariable  
   
   next()
)

然后,您可以通过 React.renderToString 传递本地,这将由客户端上的 FluxStore 选择。另一种方法,您可以使用 falcor 之类的数据获取 api,可以通过 falcor-http-datasource 由客户端 Action Store 选择,您不需要使用 falcor-express 和 falcor-router 构建 falcor 的 express local

【讨论】:

以上是关于同构 React 中的实时环境变量的主要内容,如果未能解决你的问题,请参考以下文章

create-react-app:多环境变量

我无法从我的 REACT 应用程序中读取 azure 应用程序服务配置中的环境变量

vue、react项目设置多环境变量

实时设置环境变量。谷歌大查询

构建 React 项目后如何设置节点环境变量(运行时)?

React Native Expo 环境变量