创建反应应用程序无法在构建后读取环境变量

create react app cannot read environment variable after build

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

它在构建后使用 serve 到 运行 应用程序,如果我们通过 运行ning 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,它无法读取环境变量

如何解决这个问题?

无法读取ENV var 的原因是:

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

(2) 在您 构建 您的应用程序(使用 webpack)之后,所有内容都已捆绑到一个或多个文件中。当您 运行 serve 时,您只需启动一个为 static 构建文件提供服务的 HTTP 服务器。因此无法将 ENV 通过管道传输到您的应用程序。

基本上 DefinePlugin 所做的就是向捆绑包中添加一个 var。例如

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

将添加类似这样的一行:

var token = '12356234ga5q3aesd';

因为 JS 文件是 static 没有办法改变这个变量 after 你 build/bundled 它与webpack。基本上,当您执行 npm run build 时,您正在创建已编译的二进制文件/.dll/.jar/... 文件并且不能再通过插件影响其内容。

您可以将 .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)

来自create-react-app documentation

Your project can consume variables declared in your environment as if they were declared locally in your JS files. By default you will have NODE_ENV defined for you, and any other environment variables starting with 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>
  );
} 

如果您在 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} 和他们在一起。所以,你只能运行这一次,因为块正在被覆盖。