【问题标题】:create react app cannot read environment variable after build构建后创建反应应用程序无法读取环境变量
【发布时间】:2018-01-15 14:48:31
【问题描述】:

我有一个 react 应用程序,使用 create-react-app 创建,然后我使用命令构建应用程序:npm run build

它在构建后使用serve 运行应用程序,如果我们通过运行ENV=production npm run start 使用开发代码启动应用程序,它可以读取process.env.ENV 变量,因为我正在将此插件添加到webpack 开发配置

   new webpack.DefinePlugin({
      'process.env':{
        'ENV': JSON.stringify(process.env.ENV),
      }
    }),

我还将上面的脚本添加到 webpack prod config,但是如果我在构建 ENV=prod serve -s build 后尝试此命令,它无法读取环境变量

如何解决这个问题?

【问题讨论】:

    标签: node.js reactjs webpack create-react-app


    【解决方案1】:

    如果您在app.config.js 中设置了所有环境变量,则可以在main.????????.chunk.js 文件中在构建后 替换它们。

    app.config.js 示例可能如下所示:

    export default {
      SOME_URL: "https://${ENV_VAR_1}"
      SOME_CONFIGURATION: "${ENV_VAR_2}",
    }
    

    保持app.config.js 文件不变,将环境变量替换为其实际值。然后,创建优化的生产版本:

    npm ci # if not already installed
    npm run build
    

    如果使用默认的 webpack 配置,app.config.js 的内容将被捆绑在build/static/js/main.????????.chunk.js 中。环境变量的值可以是envsubst,bash 脚本如下:

    main_chunk=$(ls build/static/js/main.*.js)
    envsubst <$main_chunk >./main_chunk_temp
    cp ./main_chunk_temp $main_chunk
    rm ./main_chunk_temp
    

    注意:在上面的示例中,envsubst 在运行时读取环境中设置的实际变量,字面意思用它们替换${ENV_VAR_1}${ENV_VAR_2}。因此,您只能运行一次,因为该块正在被覆盖。

    【讨论】:

    • 我在哪里设置 app.config.js 文件会在根目录中,以及如何在构建后使用它来更改环境变量?
    【解决方案2】:

    看不到ENV var的原因是:

    (1) 在开发 模式下,webpack 实时监视您的文件和捆绑您的应用程序。它还将读取(由于DefinePlugin)您的process.env.ENV 并将其添加为全局变量。所以它基本上是从process.env 到你的 JS 应用程序的管道变量。

    (2) 在您构建您的应用程序(使用webpack)之后,所有内容都已捆绑到一个或多个文件中。当您运行serve 时,您只需启动一个为静态 构建文件提供服务的HTTP 服务器。所以没有办法将ENV 传递给你的应用程序。

    基本上DefinePlugin 所做的是将var 添加到捆绑包中。例如

    new webpack.DefinePlugin({
      'token': '12356234ga5q3aesd'
    })
    

    会添加类似这样的一行:

    var token = '12356234ga5q3aesd';
    

    由于 JS 文件是 静态的,因此在您使用 webpack 构建/捆绑它之后, 无法更改此变量。基本上,当您执行npm run build 时,您正在创建已编译的二进制/.dll/.jar/... 文件,并且无法再通过插件影响其内容。

    【讨论】:

    • 所以解决方案是,我必须添加一个带有DefinePlugin 的静态标志变量,告诉它是生产还是开发,对吗?或者有什么解决办法?
    • 是的,CRA 已设置为将 process.env 下的所有内容添加到定义插件。见github.com/facebookincubator/create-react-app/blob/… 它还会自动为你设置prod/dev -> process.env.NODE_ENV
    • @SebastianSebald 关于捆绑发生在构建时是正确的。但实际上有一种方法可以在构建后替换 ENV 变量,这就是我们公司正在做的事情:stackoverflow.com/a/61881757/5465000
    【解决方案3】:

    您可以将.env 文件添加到项目的根目录并在那里定义您的环境变量。这将是您的默认(生产)环境变量定义。但是你可以有一个名为 .env.local 的本地文件来覆盖默认值。

    定义环境变量时,请确保它们以REACT_APP_ 开头,这样您的环境变量定义将如下所示:

    REACT_APP_SERVER_URL=https://my-awesome-app.herokuapp.com
    

    另外,将此添加到 .gitignore 中,这样您就不会提交本地覆盖:

    .env*.local
    

    参考: Adding Development Environment Variables In .env (create-react-app)

    【讨论】:

    • 如果我正在运行一个已经捆绑了 webpack 的 react 应用程序(使用 create-react-app myapp)。我需要做任何事情来包含 .env 吗?如果我有多个 .env 我需要做些什么吗?
    • 如果构建已捆绑,此解决方案将不起作用。 .env 文件及其REACT_APP 变量是在构建期间而不是在服务时读取的!
    【解决方案4】:

    来自create-react-app documentation

    您的项目可以像使用环境中声明的变量一样 它们是在您的 JS 文件中本地声明的。默认情况下,您将拥有 为您定义的 NODE_ENV,以及任何其他开始的环境变量 使用 REACT_APP_。

    您可以从代码中的 process.env 中读取它们:

    render() {
      return (
        <div>
          <small>You are running this application in <b>{process.env.NODE_ENV}</b> mode.</small>
          <form>
            <input type="hidden" defaultValue={process.env.REACT_APP_NOT_SECRET_CODE} />
          </form>
        </div>
      );
    } 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-01-24
      • 2021-11-03
      • 2019-05-30
      • 1970-01-01
      • 2021-10-04
      • 1970-01-01
      • 1970-01-01
      • 2018-12-13
      相关资源
      最近更新 更多