【问题标题】:How to set up dynamic environment configurations in React如何在 React 中设置动态环境配置
【发布时间】:2021-01-26 06:00:38
【问题描述】:

我的目标是找到一种方法,为我的 React 应用程序的各种“轨道”动态提取特定于环境的配置值:开发、登台和生产。最常规定的解决方案涉及使用环境变量,我觉得这不是很好,因为:

  1. 我的一些配置值是敏感数据,例如 API 密钥、数据库密码等,我理想情况下不会在本地和本地以纯文本形式保存这些数据在 CICD 系统上
  2. 必须手动设置环境变量容易出错并且不能很好地扩展(这是一个大型项目,需要设置 20 多个与配置相关的键值对)。记录需要设置哪些环境变量也很困难,因此对于多协作团队来说这不是一个方便的解决方案,因为每个人都需要跟踪列表并将值复制粘贴到他们的本地机器中以共享 API 密钥等(或者更糟糕的是,将它们硬编码/检查到源代码中)

我尝试了以下两种通用方法:

  1. 使用node-config - 它看起来很有前途,因为它轻巧、灵活且可扩展(它允许在default.js 上定义基值并用development.jsstaging.jsproduction.js 或自定义环境变量覆盖它们) .最重要的是,我们可以将机密存储在远程服务中(例如 AWS/GCP Secrets Manager、envkey 等)。该解决方案适用于我的 Node 后端,但目前不适用于基于 React 构建的前端应用
  2. 使用dotenv(或dotenv-safe,以允许在另一个.env.example 中记录.env 文件的结构,该.env.example 已签入源代码管理)。对于我们项目需要的每个环境,这不是我喜欢的方法,因为 dotenv discourages using multiple .env files。其次,我可能仍然需要找到另一种方法将环境变量输入我的 CICD 系统。在 [remote] 构建系统上重新定义 env var 感觉就像做两次工作 - 第一次是在用于本地开发的 .env 文件上。

这两种方法都会产生一个熟悉的问题:TypeError: fs.readFileSync is not a function。根据this related question,似乎根本问题是the 'fs' module is not designed to work on the browser(dotenv 和node-config 都是底层使用'fs'的低级模块)。 如果我们不能在客户端使用 fs(或者更确切地说,依赖它的模块):可扩展/生产级 React 项目通常如何以理智的方式管理配置值?我知道hashicorp/vault存在,但它似乎有点矫枉过正,因为我们可能不得不建立自己的基础设施。

我也想知道是否有任何开源工具可以解决这个常见问题......

【问题讨论】:

  • 在基本文件的基础上创建多个 .env 文件。像 .env.dev .env.stage .env.prod。当您创建构建或启动它时,传递一个环境变量。指定环境的命令行。然后在构建或启动之前,将该 evn 的相应 env 文件的内容复制到主 .env 文件中。 React 应该正确拾取正确的骨骼 env 弹性
  • @quirimmo 我希望避免在 .env 文件之间复制粘贴。无论如何,我找到了一个基于多普勒的更好的解决方案

标签: javascript reactjs configuration environment-variables dotenv


【解决方案1】:

上面提供的两种解决方案都没有真正满足我的要求,首先因为我使用的是 create-react-app 项目,所以对 webpack 配置没有太多控制。其次,我更愿意不在本地保存 .env 文件(更不用说纯文本)

幸运的是,我遇到了https://doppler.com/,这是一个通用的秘密管理解决方案,可以解决我在 OP 中描述的需求:

  1. 它是一个基于云的秘密存储 + 管理器,带有 CLI,它允许我们在整个管道(本地开发、CICD 和生产)中使用相同的环境秘密
  2. 项目包含开发、暂存和生产环境,可以轻松在不同风格的应用之间轻松切换

因为 Doppler 通过将环境变量注入运行时来工作,所以我可以像这样使用 yarn:

doppler run -- yarn start

对于需要首先将环境变量注入捆绑应用程序(例如 firebase 模拟器)的服务器环境,首先进行“多普勒注入”构建:

doppler run -- yarn build

然后像往常一样运行模拟器: firebase emulators:start

【讨论】:

    【解决方案2】:

    使用单独的 dotenv 例如 .env.dev.env.qa 将是我目前对可扩展反应项目的方法。我假设您正在使用webpack,并且在使用fs 获取文件时遇到问题,因为fs 是一个节点服务器端模块。 要解决这个TypeError 问题,在您的webpack 配置中,您可以使用fs 访问当前工作目录,

    const fs = require('fs');
    const path = require('path');
    const reactAppDirectory = fs.realpathSync(process.cwd());
    const resolveReactApp = (relativePath) => path.resolve(reactAppDirectory, relativePath);
    

    您需要复制所有资产并构建到一个单独的 public 文件夹中,该文件夹有一个 web.config 并使用上面的 resolveReactApp('public') 在您的 devServer 配置的 contentBase 部分中的 resolveReactApp('public') 解析其路径.

    您可以使用 webpack 的 DefinePlugin 或 EnvironmentPlugin 传递环境变量,

    new webpack.DefinePlugin({
      'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
      'process.env.DEBUG': JSON.stringify(process.env.DEBUG)
    });
    
    new webpack.EnvironmentPlugin(['NODE_ENV', 'DEV']);
    

    要存储机密,我建议您查看 docker-secrets 并使用容器化架构进行部署,并且当团队进一步扩展时,也可以更轻松地进行项目设置。这是how to use docker with react 的快速设置介绍以及switching from environment variables to docker-secrets 的更多信息,以获得更好的系统架构。

    【讨论】:

    • 很棒的见解,虽然我无法走这条路,因为我无法控制 webpack 配置 - 我正在使用 CRA 应用程序
    • @kip2 查看craco。它允许您在不弹出的情况下扩展 CRA
    猜你喜欢
    • 1970-01-01
    • 2011-08-15
    • 2019-12-04
    • 2019-10-28
    • 2019-10-17
    • 2019-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多